From 41b3b7f64a64f60703f67a007f636c93d2471432 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Mon, 8 Mar 2021 00:44:14 +0100 Subject: [PATCH 01/32] Data-Mine 'Omega' --- Projects/Superalgos/Plugins/Data-Mines/Omega.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Projects/Superalgos/Plugins/Data-Mines/Omega.json diff --git a/Projects/Superalgos/Plugins/Data-Mines/Omega.json b/Projects/Superalgos/Plugins/Data-Mines/Omega.json new file mode 100644 index 000000000..0ce7c2d8e --- /dev/null +++ b/Projects/Superalgos/Plugins/Data-Mines/Omega.json @@ -0,0 +1 @@ +{"type":"Data Mine","name":"Omega","config":"{\n \"codeName\": \"Omega\"\n}","project":"Superalgos","sensorBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Fast","project":"Superalgos","id":"d3431f91-842e-459b-b969-e93269ab06ee","savedPayload":{"position":{"x":17451.72948123781,"y":40729.60591487127},"targetPosition":{"x":17509.963766385878,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"5132afea-630c-455f-be7c-8d94469a239d"}}}],"outputDatasetFolders":[],"id":"81ac5c2c-7766-44ed-8e84-94b42ffbf7ab","savedPayload":{"position":{"x":17509.963766385878,"y":40946.93922578631},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"dc491dd3-55ba-40ac-8f8e-0dd6d8e8e877","savedPayload":{"position":{"x":17570.18233668201,"y":40849.511367860556},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"5a92a4fb-51ab-4ac6-9e6c-834767b542b4"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"95097e44-2b3c-4368-84ad-73f5d6ca1d89","savedPayload":{"position":{"x":17655.549479256046,"y":40838.27257032879},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"0538007e-1eb0-4208-b848-4f7ff62588fa","savedPayload":{"position":{"x":17723.86019460776,"y":40890.68922578631},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"84ef19f0-4c0b-4cec-844c-e4b7b1758f64","savedPayload":{"position":{"x":17626.43233668201,"y":40946.93922578631},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"5a92a4fb-51ab-4ac6-9e6c-834767b542b4","savedPayload":{"position":{"x":17886.39610306789,"y":40846.0744851674},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"301b012f-4e33-4549-89c3-90bf2f992458","savedPayload":{"position":{"x":17785.531362448986,"y":41106.038251553284},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"e226b09c-b34e-493e-a9cb-c6562faa8ad2","savedPayload":{"position":{"x":17785.531362448986,"y":41222.50682184941},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0c56f6f-d2dd-4d09-bd32-98e75221d015","savedPayload":{"position":{"x":15187.198051533946,"y":41176.27253670135},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Fast","project":"Superalgos","id":"c2993196-c4fb-4804-99b7-bf15c2f9e899","savedPayload":{"position":{"x":18150,"y":40703.047724829295},"targetPosition":{"x":17925,"y":41092.759156532295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"82f018e1-8fbd-4f93-b708-7bced5b23671"}}}],"outputDatasetFolders":[],"id":"d19d52df-3197-47d4-9f1d-c58b6fda2a87","savedPayload":{"position":{"x":17925,"y":41092.759156532295},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"60ec7290-4564-4609-93f2-046e7adefd51","savedPayload":{"position":{"x":18334.79899745976,"y":40880.068832659854},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"46093d66-daaa-4f01-b9e8-2c8001878a4e"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"0f7886f9-2cb3-403a-a71a-0620123d69e4","savedPayload":{"position":{"x":18439.427114358634,"y":40974.276412262865},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"fca6d255-88bf-43e1-947c-8b52cf9c8410","savedPayload":{"position":{"x":18509.822623626736,"y":41096.20501093991},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"5555532e-03cc-4eb3-a922-b175291abe9c","savedPayload":{"position":{"x":18539.094722342554,"y":41233.91940792597},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"2eb87964-42f6-472f-9f82-ae7ce3cc175b","savedPayload":{"position":{"x":18089.711431703,"y":41257.470588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"46093d66-daaa-4f01-b9e8-2c8001878a4e","savedPayload":{"position":{"x":18150,"y":41482.470588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"df3b3c25-507f-43b2-b620-c1163cdbbf99","savedPayload":{"position":{"x":17894.8557158515,"y":41594.970588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"63452d0d-1cf4-4bc8-9f8e-e42ddc4da4c7","savedPayload":{"position":{"x":17812.5,"y":41677.32630408679},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e83d3882-522d-47ee-a853-9fd48c52a962","savedPayload":{"position":{"x":15319,"y":41494.470588235294},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Fast","config":"{\n \"codeName\": \"fastARPS\",\n \"singularVariableName\": \"fastARPS\",\n \"pluralVariableName\": \"fastARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"5132afea-630c-455f-be7c-8d94469a239d","savedPayload":{"position":{"x":15377.438536534504,"y":41659.67228307919},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"82f018e1-8fbd-4f93-b708-7bced5b23671","savedPayload":{"position":{"x":15348.433991612474,"y":41842.79977251312},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"6256f160-7706-4ff2-ae9a-3cd8d266fddf","savedPayload":{"position":{"x":18327.13933855677,"y":42135.34585808014},"targetPosition":{"x":18030.832836378235,"y":42182.276197592204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"333362de-b155-4287-90ca-f1d19e5de3ca","savedPayload":{"position":{"x":18030.832836378235,"y":42182.276197592204},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"c28a92c4-3eb2-41d2-8e27-61293dad8ed8","savedPayload":{"position":{"x":18327.13933855677,"y":42323.06721612842},"targetPosition":{"x":18030.832836378235,"y":42276.13687661635},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b695741-ce14-4efb-af70-61fe74d65089","savedPayload":{"position":{"x":18030.832836378235,"y":42276.13687661635},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"fb21f59f-0eec-4b84-940c-c4eb222e75d9","savedPayload":{"position":{"x":18135.479270084455,"y":42433.50226198707},"targetPosition":{"x":18001.8282914562,"y":42365.40368702614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"8b4fd778-668a-4e84-84f0-c3ef86143c97","savedPayload":{"position":{"x":18001.8282914562,"y":42365.40368702614},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"f044a4b5-54d6-4fec-a35f-a384a6a8b601","savedPayload":{"position":{"x":18052.724385733636,"y":42547.40458863822},"targetPosition":{"x":17946.658368555654,"y":42441.33857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9f7c4c1a-1062-49e5-a37c-d8cff8b4de15","savedPayload":{"position":{"x":17946.658368555654,"y":42441.33857146024},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"7835dee1-825c-4467-8cf6-180ab71f04f2","savedPayload":{"position":{"x":17938.822059082486,"y":42630.15947298904},"targetPosition":{"x":17870.723484121554,"y":42496.50849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"10554c37-8b71-46a7-a58c-fa70b517a45d","savedPayload":{"position":{"x":17870.723484121554,"y":42496.50849436079},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"0cbfa484-337e-47eb-98b3-209a5683e3d4","savedPayload":{"position":{"x":17804.921843467797,"y":42673.666290372086},"targetPosition":{"x":17781.456673711764,"y":42525.513039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"cd7c2e47-4b7e-4cee-8967-820c040f8a4d","savedPayload":{"position":{"x":17781.456673711764,"y":42525.513039282814},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"01c1be70-508f-4533-af13-3654530e3eeb","savedPayload":{"position":{"x":17664.130824931588,"y":42673.666290372086},"targetPosition":{"x":17687.595994687625,"y":42525.513039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3c947876-5900-4552-8e95-aa0f77871389","savedPayload":{"position":{"x":17687.595994687625,"y":42525.513039282814},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"01086358-6fdd-462c-9a3b-89edca234dc1","savedPayload":{"position":{"x":17530.230609316895,"y":42630.15947298904},"targetPosition":{"x":17598.329184277827,"y":42496.50849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c2095ffb-e643-4a6c-91f0-ccf0e4f20982","savedPayload":{"position":{"x":17598.329184277827,"y":42496.50849436079},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"6ce6dd46-1296-4b13-afab-84d1823351b8","savedPayload":{"position":{"x":17416.328282665745,"y":42547.40458863822},"targetPosition":{"x":17522.394299843727,"y":42441.33857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7a6db1af-b519-4674-a850-10f9e64358ab","savedPayload":{"position":{"x":17522.394299843727,"y":42441.33857146024},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"36353357-8bb9-44e2-80ae-19eec60b1516","savedPayload":{"position":{"x":15353.526334199692,"y":42241.20653710428},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"// Loop Code\n\nlet nCandles = 3 // Change here number of candles to use\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// End of Code :-)","project":"Superalgos","id":"ad10cba8-9086-4846-af86-00082eb86754","savedPayload":{"position":{"x":15060.333810660808,"y":42251.539598611875},"targetPosition":{"x":15049.880964334043,"y":42152.087409075044},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b749a547-69ea-47fb-837f-1190a5ec2ebd","savedPayload":{"position":{"x":15049.880964334043,"y":42152.087409075044},"targetPosition":{"x":15034.201694843894,"y":42002.9091247698},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"955d2caa-e4d0-4e19-bf62-1d48f44c5a69","savedPayload":{"position":{"x":14932.517534074945,"y":42231.295489180455},"targetPosition":{"x":14973.191198382525,"y":42139.94094341619},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b4cb1e91-d42e-4165-8598-73874f217df5","savedPayload":{"position":{"x":14973.191198382525,"y":42139.94094341619},"targetPosition":{"x":15034.201694843894,"y":42002.9091247698},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"32fc144f-fcf7-4e27-a4ce-9964a6240653","savedPayload":{"position":{"x":15034.201694843894,"y":42002.9091247698},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fe7a8b58-37c4-4e51-a037-6eedcd8e9dfb","savedPayload":{"position":{"x":15081.132034355964,"y":41706.60262259126},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS","id":"2675db9e-a697-4f84-a252-8c27ed423e24"}}}],"id":"892f3bfe-6b06-491b-994a-825c96bf0e72","savedPayload":{"position":{"x":14869,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Chaikin Oscillator Data Procedure","project":"Superalgos","id":"ba931d51-1350-4df7-a2d5-2eff15cf844a","savedPayload":{"position":{"x":15417.430428875681,"y":41180.299462731185},"targetPosition":{"x":15336.79764022799,"y":41390.35505869306},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"ec6522f5-9165-4607-87a6-ea63e2f4d20e"}}}],"outputDatasetFolders":[],"id":"28505aa2-26a8-479c-bba7-782ed4066ca0","savedPayload":{"position":{"x":15336.79764022799,"y":41390.35505869306},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"ad424254-a304-41bb-9ba9-b8267455e0d2","savedPayload":{"position":{"x":15697.396278927989,"y":41111.66875071292},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"72244463-734d-4495-9eab-9ed63818963d"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"ee83aebb-ffed-415b-91c1-0f6fa3f79dfd","savedPayload":{"position":{"x":15756.434920666677,"y":41150.008892950085},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"2d08d62e-f0a9-45b4-b148-6fe217fdf5c6","savedPayload":{"position":{"x":15800.736250087433,"y":41204.7164786825},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"9b1e61f2-fd52-4ee2-9c57-ede4bbe084de","savedPayload":{"position":{"x":15825.96374440104,"y":41270.436348248506},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"775e3d6e-71ed-4b61-a632-a80aefddbd49","savedPayload":{"position":{"x":15605.880534235934,"y":41317.2164786825},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"72244463-734d-4495-9eab-9ed63818963d","savedPayload":{"position":{"x":15700.62460484811,"y":41530.015145386824},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"11d0bcf4-9c53-428c-9fff-feb3f72c4ad1","savedPayload":{"position":{"x":15466.220447542168,"y":41681.043443302624},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"ff07193a-4761-45da-a5b0-d4a0f65d5dbb","savedPayload":{"position":{"x":15397.76193956651,"y":41775.268495982746},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7abd43da-a0dc-477c-b6eb-9e63b21e5262","savedPayload":{"position":{"x":15256.164851580297,"y":41600.41065465493},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Chaikin Oscillator Data Procedure","project":"Superalgos","id":"d3a96bb9-4c2d-4bbd-ada0-1c8bb456fffe","savedPayload":{"position":{"x":15997.953657659551,"y":41569.246548686424},"targetPosition":{"x":15586.85820172038,"y":41752.27803807054},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"bcb93023-ae74-48f0-a26b-2f2d57c57740"}}}],"outputDatasetFolders":[],"id":"4858b9f4-4354-4e9a-9581-da02aa2619e1","savedPayload":{"position":{"x":15586.85820172038,"y":41752.27803807054},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Daily","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"973153da-c1d7-4643-a367-21c40ce30ebd","savedPayload":{"position":{"x":16034.393054636104,"y":41799.31584654098},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"4a5ee296-a995-48fe-b8ac-1b7e54cbdcdd"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"8327acb7-ef19-4e57-b44d-2871da44d621","savedPayload":{"position":{"x":16067.757351964747,"y":41911.95182665699},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{\n \"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"209f3ffc-3c8b-4e5f-91ce-80e8c5f41bf1","savedPayload":{"position":{"x":16070.832451612658,"y":42029.385144395535},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"93f3541a-f954-4980-bcc8-4e0ae868f5ca","savedPayload":{"position":{"x":16043.408790620675,"y":42143.61291322048},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"65ae3b73-5a3e-411e-ac6c-332f0f8a36a1","savedPayload":{"position":{"x":15987.35524616566,"y":42246.85069945671},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"927e58b1-c870-45e0-b256-eb3fb22d9302","savedPayload":{"position":{"x":15623.297598696934,"y":41982.34733592509},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"4a5ee296-a995-48fe-b8ac-1b7e54cbdcdd","savedPayload":{"position":{"x":15539.820393249936,"y":42199.812890986264},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"5f26534d-432d-4be2-9aa8-0aa452dc95c6","savedPayload":{"position":{"x":15267.278490473265,"y":42140.857255424235},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"11ee3e01-af54-40ed-b3ac-fde2d322cd7e","savedPayload":{"position":{"x":15152.24384154599,"y":42159.07695391251},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e60b83a0-fb61-4bf2-87dc-9a3c444153b9","savedPayload":{"position":{"x":15175.76274578121,"y":41935.30952745465},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Chaikin Oscillator Data Procedure","config":"{\n \"codeName\": \"ChaikinOscillator\",\n \"singularVariableName\": \"ChaikinOscillator\",\n \"pluralVariableName\": \"ChaikinOscillators\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"ec6522f5-9165-4607-87a6-ea63e2f4d20e","savedPayload":{"position":{"x":15125.937395081064,"y":42103.309816023444},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"bcb93023-ae74-48f0-a26b-2f2d57c57740","savedPayload":{"position":{"x":14994.832587746418,"y":42234.41462335809},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"59d6bee5-111c-4309-8070-ebe49c60285a","savedPayload":{"position":{"x":15231.062335674598,"y":42937.31790508857},"targetPosition":{"x":14997.918547237507,"y":42748.521787773614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"4a56532a-32af-4c09-861a-7b0ec19aa90f","savedPayload":{"position":{"x":14997.918547237507,"y":42748.521787773614},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"cac1f7d5-bba0-487e-8a88-96d241085815","savedPayload":{"position":{"x":14979.795528527595,"y":43119.87392635699},"targetPosition":{"x":14872.285143664005,"y":42839.799798407825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0d2e4662-fbdf-490b-8553-b069cf732f62","savedPayload":{"position":{"x":14872.285143664005,"y":42839.799798407825},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if ( isNaN(variable.chaikinOscillator ) )\n{ variable.chaikinOscillator = 0 }\nelse\n{ variable.chaikinOscillator }","project":"Superalgos","id":"c0570b4b-c935-4511-80a0-965874de3aab","savedPayload":{"position":{"x":14694.37924953231,"y":43004.18542372648},"targetPosition":{"x":14717.844419288345,"y":42856.032172637206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f07b74fd-4beb-409b-99e1-ed51c746bc63","savedPayload":{"position":{"x":14717.844419288345,"y":42856.032172637206},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Zero Line","config":"{\n \"codeName\": \"zeroLine\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"0","project":"Superalgos","id":"c37d5f0d-81f7-46bc-9693-9d854f2d4190","savedPayload":{"position":{"x":14481.580582827988,"y":42909.4413531143},"targetPosition":{"x":14575.978641485464,"y":42792.86945889575},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b5d9bc2b-386e-4670-abee-e828107a5015","savedPayload":{"position":{"x":14575.978641485464,"y":42792.86945889575},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"ADL","config":"{\n \"codeName\": \"ADL\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.accDistLine))\n{ variable.accDistLind = 0 }\nelse\n{ variable.accDistLine }","project":"Superalgos","id":"f617da69-165b-4875-88d6-0edfa8769d2f","savedPayload":{"position":{"x":14344.663566876674,"y":42720.99124775405},"targetPosition":{"x":14484.700630851254,"y":42667.23605532225},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c105d752-f310-4917-ac54-65ff02021576","savedPayload":{"position":{"x":14484.700630851254,"y":42667.23605532225},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e5529d72-8e8d-4a32-b700-13bdb3ab4dd0","savedPayload":{"position":{"x":14764.774758800415,"y":42559.72567045866},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Loop Code */\n\n/* Chaikin Oscillator\n\nKEY TAKEAWAYS\n- The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n- A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish.\n\n1. Money Flow Multiplier = [(Close - Low) - (High - Close)] / (High - Low) \n2. Money Flow Volume = Money Flow Multiplier x Volume for the Period\n3. ADL = Previous ADL + Current Period's Money Flow Volume\n4. Chaikin Oscillator = ('fast'-period EMA of ADL) - ('slow'-period EMA of ADL) */\n\n\nlet fastPeriod = 5 // Change value to set 'fast' period (must be less than or equal to 'fast')\nlet slowPeriod = 17 // Change value to set 'slow' period (must be greater than or equal to 'slow')\n\nlet candle = record.current\nlet volume = getElement('volumes', candle)\n\n\n// Set varibles\nvariable.totalVolume = volume.buy + volume.sell\t\nvariable.moneyFlowMultiplier = ((candle.close - candle.min) - (candle.max - candle.close)) / (candle.max - candle.min) \nvariable.moneyFlowVolume = variable.moneyFlowMultiplier * variable.totalVolume \nvariable.currentADL = variable.totalVolume + variable.moneyFlowVolume\nvariable.savedADL.push(variable.currentADL) // Push the currentADL into an array to be able to use \"previous ADL\"\n\nif (variable.savedADL.length > 2) { // Make sure we only save the current and previous\n variable.savedADL.splice(0, 1)\n}\n\n// Calculating the 'accDistLine' using previous ADL value if it is defined, else current\nif (variable.savedADL[0] === 'undefined')\n{variable.accDistLine = variable.savedADL[1] + variable.moneyFlowVolume} // Calculating with Current ADL\nelse\n{variable.accDistLine = variable.savedADL[0] + variable.moneyFlowVolume} // Calculating with Previous ADL\n\n\n// Calculate fastEMA and slowEMA of ADL\nif(isNaN(variable.previousEmaFast))\n{variable.previousEmaFast = variable.accDistLine}\nelse\n{variable.previousEmaFast}\n\nvariable.fastEMA = calculateEMAs(fastPeriod, variable.accDistLine, variable.previousEmaFast)\nvariable.previousEmaFast = variable.fastEMA\n\nif(isNaN(variable.previousEmaSlow))\n{variable.previousEmaSlow = variable.accDistLine}\nelse\n{variable.previousEmaSlow}\nvariable.slowEMA = calculateEMAs(slowPeriod, variable.accDistLine, variable.previousEmaSlow)\nvariable.previousEmaSlow = variable.slowEMA\n\n\n// Create EMA function for 'fast' and 'slow' ADL\nfunction calculateEMAs(periods, adl, previousEMA) {\n let k = 2 / (periods + 1)\n return adl * k + previousEMA * (1-k)\n}\n\n// Calculate Chaikin Oscillator value\nvariable.chaikinOscillator = variable.fastEMA - variable.slowEMA\n\n/*\n// Printing values to console to check\nconsole.log(\"Volume: \", variable.totalVolume)\nconsole.log(\"MF x: \", variable.moneyFlowMultiplier)\nconsole.log(\"MF Vol: \", variable.moneyFlowVolume)\nconsole.log(\"Current ADL: \", variable.currentADL)\nconsole.log(\"AccDistLine: \", variable.accDistLine)\nconsole.log(\"Fast EMA: \", variable.fastEMA)\nconsole.log(\"Slow EMA: \", variable.slowEMA)\nconsole.log(\"Chaikin Oscillator: \", variable.chaikinOscillator)\n*/","project":"Superalgos","id":"c0132fa6-7f08-4457-9656-05bba93d9cca","savedPayload":{"position":{"x":14521.50340346859,"y":42395.751051403655},"targetPosition":{"x":14571.50340346859,"y":42309.14851102521},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"01efe8a3-bfc2-43ee-b29e-a72c9fa7ab5f","savedPayload":{"position":{"x":14571.50340346859,"y":42309.14851102521},"targetPosition":{"x":14646.50340346859,"y":42179.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build arrays \n\nvariable.savedADL = []\n\n","project":"Superalgos","id":"6199432b-91d5-471d-b5e2-5cbbfeed340c","savedPayload":{"position":{"x":14429.99705252248,"y":42304.244700457544},"targetPosition":{"x":14516.599592900924,"y":42254.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2ea55eba-609e-4780-8333-7ca25058c8ab","savedPayload":{"position":{"x":14516.599592900924,"y":42254.244700457544},"targetPosition":{"x":14646.50340346859,"y":42179.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4be72b8f-5821-473b-9b38-26c665856101","savedPayload":{"position":{"x":14646.50340346859,"y":42179.244700457544},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"14ad8763-cbf9-43e0-8132-16be260a8d2c","savedPayload":{"position":{"x":14858.635437824554,"y":41967.11266610158},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Chaikin Oscillator","id":"653018cc-a18a-4370-a6c5-e0ad879b2c2f"}}}],"id":"627939de-3884-4de8-99a9-35d0e66fa2d4","savedPayload":{"position":{"x":14781.132034355964,"y":41706.60262259126},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Slow ARPS","project":"Superalgos","id":"03519cbc-2f6a-4ac2-9c28-e33e61384619","savedPayload":{"position":{"x":16874.72948123781,"y":41057.10591487127},"targetPosition":{"x":16932.963766385874,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"c7403fbf-2ca8-41b4-8e24-a5ec34818127"}}}],"outputDatasetFolders":[],"id":"27246891-a94e-4a4e-9cb1-b7487c876f47","savedPayload":{"position":{"x":16932.963766385874,"y":41274.43922578631},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"76089903-5360-4ee6-ae07-dcc91ed96482","savedPayload":{"position":{"x":16993.18233668201,"y":41177.011367860556},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2b630c1d-86e7-4144-be9e-b7ba0ae8ecf6"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"50b106cc-4d03-499e-a5a3-e1aa4cd8215c","savedPayload":{"position":{"x":17078.549479256042,"y":41165.77257032879},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"d9a2dab2-c16a-4d07-9978-77e9bf72f5d2","savedPayload":{"position":{"x":17146.86019460776,"y":41218.18922578631},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"90f657aa-0f1f-43c2-ab2d-c91a6cfba4b6","savedPayload":{"position":{"x":17049.43233668201,"y":41274.43922578631},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"2b630c1d-86e7-4144-be9e-b7ba0ae8ecf6","savedPayload":{"position":{"x":17309.39610306789,"y":41173.5744851674},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"087388b9-9acb-40ac-b76e-23bf36e35f05","savedPayload":{"position":{"x":17208.531362448986,"y":41433.538251553284},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"57d2e4a3-6ed0-4b57-a107-39438f91b0e9","savedPayload":{"position":{"x":17208.531362448986,"y":41550.00682184941},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c4f909d9-665a-41ee-9dce-d8e75ea7a43f","savedPayload":{"position":{"x":14356.867965644036,"y":42156.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Slow ARPS","project":"Superalgos","id":"45e34e9d-ef1b-4273-a805-def2f0d4092f","savedPayload":{"position":{"x":17573,"y":41030.547724829295},"targetPosition":{"x":17348,"y":41420.259156532295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"4bff21d4-3de0-4e8e-9f63-b7792996247d"}}}],"outputDatasetFolders":[],"id":"d47a3468-9012-45ea-8c97-317d574f239b","savedPayload":{"position":{"x":17348,"y":41420.259156532295},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"0ce21a09-c93a-499b-8367-f9abf9192022","savedPayload":{"position":{"x":17757.79899745976,"y":41207.568832659854},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a4e156b7-d673-49b0-81bf-6d3d503abd34"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"09887b9d-20ed-4069-b794-d0ad12ec4847","savedPayload":{"position":{"x":17862.42711435863,"y":41301.776412262865},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"febb0ddf-d6b6-4930-9620-58e0033a3e14","savedPayload":{"position":{"x":17932.822623626736,"y":41423.70501093991},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"a9bcd7f0-525e-4eea-a2ad-0e6f987e5799","savedPayload":{"position":{"x":17962.094722342554,"y":41561.41940792597},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"d237a234-82ae-473d-9659-0433797141b0","savedPayload":{"position":{"x":17512.711431703,"y":41584.970588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"a4e156b7-d673-49b0-81bf-6d3d503abd34","savedPayload":{"position":{"x":17573,"y":41809.970588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"c02c96bc-833b-4463-b774-a6753f47278c","savedPayload":{"position":{"x":17317.855715851496,"y":41922.470588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"9087ca64-0068-4292-8d22-9228c58f34c5","savedPayload":{"position":{"x":17235.5,"y":42004.82630408679},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"6d1b63a8-1ea2-47f3-8349-499c63f39446","savedPayload":{"position":{"x":14038.66991411009,"y":42024.8006741252},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Slow ARPS","config":"{\n \"codeName\": \"slowARPS\",\n \"singularVariableName\": \"slowARPS\",\n \"pluralVariableName\": \"slowARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"c7403fbf-2ca8-41b4-8e24-a5ec34818127","savedPayload":{"position":{"x":13880.532389956294,"y":41949.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"4bff21d4-3de0-4e8e-9f63-b7792996247d","savedPayload":{"position":{"x":13771.551010755491,"y":41799.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"1ab4b7a0-7c36-4ab7-8db3-1485543531b2","savedPayload":{"position":{"x":17750.13933855677,"y":42462.84585808014},"targetPosition":{"x":17453.832836378235,"y":42509.776197592204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"26848c50-95de-4b02-bc64-38b35ba53578","savedPayload":{"position":{"x":17453.832836378235,"y":42509.776197592204},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"a2f026df-7bfd-46a9-937e-2ebcf911b373","savedPayload":{"position":{"x":17750.13933855677,"y":42650.56721612842},"targetPosition":{"x":17453.832836378235,"y":42603.63687661635},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b80933e3-e479-4d3c-a4ee-c5f81266839e","savedPayload":{"position":{"x":17453.832836378235,"y":42603.63687661635},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"9a85c68f-55f6-4400-b541-e6fbef799189","savedPayload":{"position":{"x":17558.479270084455,"y":42761.00226198707},"targetPosition":{"x":17424.8282914562,"y":42692.90368702614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"864fb9fd-074e-47ff-8b46-741e984babad","savedPayload":{"position":{"x":17424.8282914562,"y":42692.90368702614},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"6ebf0e39-e7e9-41d2-9419-58dd5037f95f","savedPayload":{"position":{"x":17475.724385733636,"y":42874.90458863822},"targetPosition":{"x":17369.658368555654,"y":42768.83857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"08b55166-37ee-4088-9878-8b8954315cee","savedPayload":{"position":{"x":17369.658368555654,"y":42768.83857146024},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"9b6e5a56-c971-42c5-9eda-919e82fc653b","savedPayload":{"position":{"x":17361.822059082486,"y":42957.65947298904},"targetPosition":{"x":17293.723484121554,"y":42824.00849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2d5b640c-0bf8-4170-a216-d1a75e321225","savedPayload":{"position":{"x":17293.723484121554,"y":42824.00849436079},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"c4b17d80-7441-482b-b920-89d68f56553e","savedPayload":{"position":{"x":17227.921843467797,"y":43001.166290372086},"targetPosition":{"x":17204.456673711764,"y":42853.013039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7833873a-bac5-4646-87e8-c8c2ae5409a2","savedPayload":{"position":{"x":17204.456673711764,"y":42853.013039282814},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"681f8933-bb6c-4311-92ff-215eb5a37f33","savedPayload":{"position":{"x":17087.130824931584,"y":43001.166290372086},"targetPosition":{"x":17110.595994687625,"y":42853.013039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9dcd16cf-c609-43b7-896f-3f5d7209ae7e","savedPayload":{"position":{"x":17110.595994687625,"y":42853.013039282814},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"ab02063d-1b37-4024-b0fa-ee38859a6b50","savedPayload":{"position":{"x":16953.230609316895,"y":42957.65947298904},"targetPosition":{"x":17021.329184277827,"y":42824.00849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2f44af53-9e90-4943-989c-54b2520c65aa","savedPayload":{"position":{"x":17021.329184277827,"y":42824.00849436079},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"c20bbde5-2d5b-4a30-9c6e-f98155159f5d","savedPayload":{"position":{"x":16839.328282665745,"y":42874.90458863822},"targetPosition":{"x":16945.394299843727,"y":42768.83857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"93555a22-0783-448a-be65-e529d4f8e685","savedPayload":{"position":{"x":16945.394299843727,"y":42768.83857146024},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ee9dcc1e-1f97-417a-bc3a-03ed97bf942b","savedPayload":{"position":{"x":13486.234055866944,"y":41521.19242596629},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"// Loop Code\n\nlet nCandles = 17 // Change here number of candles to use\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// End of Code :-)","project":"Superalgos","id":"966b7e24-c167-459d-8975-5a7b4e6b8d5e","savedPayload":{"position":{"x":13686.245899592052,"y":41306.56742651631},"targetPosition":{"x":13763.960495737749,"y":41369.499465621295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c17982f3-0168-48b9-90ac-b7bef7cdaa07","savedPayload":{"position":{"x":13763.960495737749,"y":41369.499465621295},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"b324a567-8972-40c1-9e4b-ece388320ef1","savedPayload":{"position":{"x":13790.940402569968,"y":41230.50241765447},"targetPosition":{"x":13826.777197524498,"y":41323.86046030419},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ce407fea-a38d-4b44-abb5-2195ffc010e3","savedPayload":{"position":{"x":13826.777197524498,"y":41323.86046030419},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ba9e95be-ac7a-43ca-8709-08a562dce5be","savedPayload":{"position":{"x":13880.532389956294,"y":41463.89752427877},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d56a976b-05eb-4aa5-9608-d8839690052c","savedPayload":{"position":{"x":14056.867965644036,"y":41706.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Slow","id":"ba1f7fe7-29a3-4cf2-b185-dc2c65e5cc5a"}}}],"id":"66aba56e-6265-4de6-baa9-eaea3f5fd8b8","savedPayload":{"position":{"x":14569,"y":41794.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market averageVsAverage","project":"Superalgos","id":"ff8f0062-8f35-45b5-9640-7998961fa0b8","savedPayload":{"position":{"x":14605.61507507505,"y":42398.460093163274},"targetPosition":{"x":14430.75723374723,"y":42256.86300517706},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2fa9132f-8809-4ab6-a7d3-21769b765195"}}}],"outputDatasetFolders":[],"id":"97c82560-d099-42c7-8d64-b8dc57e522ec","savedPayload":{"position":{"x":14430.75723374723,"y":42256.86300517706},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"70ebbcf2-3a50-4b5d-b857-a1bd35617a0b","savedPayload":{"position":{"x":14445.198836524623,"y":42354.43865572675},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"27ca72af-be47-4d79-9b0c-dadda0003dd2"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"964c9245-0231-4904-8625-db801ad1fa00","savedPayload":{"position":{"x":14407.33072506021,"y":42412.750433816625},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"445b8c4a-cfcf-4e00-b334-8eba9c4ce149","savedPayload":{"position":{"x":14342.419976144434,"y":42437.667335812606},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"1bc1b344-3f7d-48b7-950c-c85db9d23d2d","savedPayload":{"position":{"x":14275.260289627913,"y":42419.67195204658},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"38f8eb3e-5d3b-43c4-b303-d9d63e2b75b9","savedPayload":{"position":{"x":14336.532181067103,"y":42325.32151315272},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"27ca72af-be47-4d79-9b0c-dadda0003dd2","savedPayload":{"position":{"x":14185.503883151307,"y":42559.725670458654},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"0f18ef7c-8f85-43f3-81dd-d942b1317690","savedPayload":{"position":{"x":14114.302304433199,"y":42290.12375851866},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"7bc96372-69d4-4b2a-9a50-3aa19a47bb65","savedPayload":{"position":{"x":14045.84379645754,"y":42195.89870583854},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ae0de8e8-9ccc-480f-938c-cb05d8cba570","savedPayload":{"position":{"x":14356.867965644036,"y":42156.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily averageVsAverage","project":"Superalgos","id":"624d6b5e-41d4-4bd9-a445-21dd56645dc3","savedPayload":{"position":{"x":14056.312871159678,"y":42830.37923328609},"targetPosition":{"x":14009.275062689234,"y":42382.84438037037},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"144e811d-ea2c-41d9-9c5b-68f6ba800157"}}}],"outputDatasetFolders":[],"id":"6255fc01-a43a-4ac9-9e81-1013d85c6b12","savedPayload":{"position":{"x":14009.275062689234,"y":42382.84438037037},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"f0e71f8c-1f06-426d-8cc5-35a631c8e096","savedPayload":{"position":{"x":13826.243573305124,"y":42793.93983630954},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"f11c0a9b-276d-4e7c-8369-784bea139ced"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"207c7107-7169-4143-b9bc-627f1d4a92da","savedPayload":{"position":{"x":13708.810255566576,"y":42790.86473666163},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"e5d78941-5578-4385-a414-5273061e512a","savedPayload":{"position":{"x":13596.17427545057,"y":42757.50043933299},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"68f9c948-a066-447b-870a-86238da7c2ff","savedPayload":{"position":{"x":13496.011588862253,"y":42696.12066604946},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"56a9550b-8f7b-46b5-803f-f517209e23c2","savedPayload":{"position":{"x":13415.148117365954,"y":42610.90834692543},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"76ba561f-3ffb-48cf-9c10-bbe6387e1a0f","savedPayload":{"position":{"x":13779.20576483468,"y":42346.40498339382},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"f11c0a9b-276d-4e7c-8369-784bea139ced","savedPayload":{"position":{"x":13598.179606750064,"y":42199.812890986264},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"24742d14-280e-4f10-8602-bdd2862f4625","savedPayload":{"position":{"x":13738.469827760928,"y":41958.82843168987},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"716ce0a4-f43e-4f76-8101-20a577815d99","savedPayload":{"position":{"x":13756.689526249203,"y":41843.793782762594},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0452a39-e3ec-4b20-bd70-0ebcb12c6246","savedPayload":{"position":{"x":14038.66991411009,"y":42024.8006741252},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"averageVsAverage","config":"{\n \"codeName\": \"averageVsAverage\",\n \"singularVariableName\": \"averageVsAverage\",\n \"pluralVariableName\": \"averageVsAverages\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"2fa9132f-8809-4ab6-a7d3-21769b765195","savedPayload":{"position":{"x":13880.532389956294,"y":41949.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"144e811d-ea2c-41d9-9c5b-68f6ba800157","savedPayload":{"position":{"x":13771.551010755491,"y":41799.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"938c01c4-07de-4033-bdaa-17d8fb09d38a","savedPayload":{"position":{"x":12646.856347572095,"y":42200.0096619911},"targetPosition":{"x":13071.120416284024,"y":41775.74559327917},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"35c4d523-27c6-48c2-b2a1-2b4b63c2e84c","savedPayload":{"position":{"x":13071.120416284024,"y":41775.74559327917},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"e78d81f6-95be-4eee-a18e-5bfa7640c553","savedPayload":{"position":{"x":12426.176655969914,"y":41896.2701242547},"targetPosition":{"x":12960.780570482933,"y":41623.87582441097},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"05257927-f8b2-4a8b-a50e-a04c1efc3a3e","savedPayload":{"position":{"x":12960.780570482933,"y":41623.87582441097},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"fastPriceRange","config":"{\n \"codeName\": \"fastPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.fastPriceRange)) {\nvariable.fastPriceRange\n}\nelse {\nvariable.fastPriceRange = 1\n}","project":"Superalgos","id":"46081807-6648-45a7-a65a-16a9e8da966d","savedPayload":{"position":{"x":13050.924731728142,"y":41421.87703383534},"targetPosition":{"x":13199.077982817413,"y":41398.41186407931},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5307878c-aafa-410b-b43a-0bcd0020bb08","savedPayload":{"position":{"x":13199.077982817413,"y":41398.41186407931},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"slowPriceRange","config":"{\n \"codeName\": \"slowPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.slowPriceRange)) { \nvariable.slowPriceRange\n}\nelse { \nvariable.slowPriceRange = 1\n}","project":"Superalgos","id":"9e21a59a-9c44-47f3-be7f-5c03e8e945ef","savedPayload":{"position":{"x":13050.924731728142,"y":41281.086015299144},"targetPosition":{"x":13199.077982817413,"y":41304.55118505518},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"fdcb9976-a574-40be-bf72-1719da5dcd4e","savedPayload":{"position":{"x":13199.077982817413,"y":41304.55118505518},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"longTermPriceRange","config":"{\n \"codeName\": \"longTermPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.longTermPriceRange)) {\nvariable.longTermPriceRange\n}\nelse {\nvariable.longTermPriceRange = 1\n}","project":"Superalgos","id":"2e627fae-2cb1-4f65-84a6-e77c6e88fa17","savedPayload":{"position":{"x":13094.431549111188,"y":41147.18579968445},"targetPosition":{"x":13228.082527739443,"y":41215.28437464538},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f8988c1b-4938-4a4a-b7f9-7d77d91ce534","savedPayload":{"position":{"x":13228.082527739443,"y":41215.28437464538},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"bullPriceDeviation","config":"{\n \"codeName\": \"bullPriceDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.bullPriceDeviation)) {\nvariable.bullPriceDeviation\n}\nelse {\nvariable.bullPriceDeviation = 1\n}","project":"Superalgos","id":"908c053b-f1eb-4ea4-b545-e954ffd3db1b","savedPayload":{"position":{"x":13177.186433462008,"y":41033.2834730333},"targetPosition":{"x":13283.25245063999,"y":41139.34949021128},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"37955412-117b-41ee-a43d-b803e46416d8","savedPayload":{"position":{"x":13283.25245063999,"y":41139.34949021128},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"smaPrice","config":"{\n \"codeName\": \"smaPrice\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.smaPrice)) {\nvariable.smaPrice\n}\nelse {\nvariable.smaPrice = 1\n}","project":"Superalgos","id":"8f6487d2-ef0b-42d9-b7a3-74045069fdad","savedPayload":{"position":{"x":13291.088760113158,"y":40950.52858868248},"targetPosition":{"x":13359.18733507409,"y":41084.17956731073},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c760cbf7-ea72-4716-aca7-f6a43d60a9af","savedPayload":{"position":{"x":13359.18733507409,"y":41084.17956731073},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"volumeDeviation","config":"{\n \"codeName\": \"volumeDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.volumeDeviation)) {\nvariable.volumeDeviation\n}\nelse {\nvariable.volumeDeviation = 1\n}","project":"Superalgos","id":"50217133-ddcd-4dd5-8c05-4c284eb3a164","savedPayload":{"position":{"x":13424.988975727849,"y":40907.02177129943},"targetPosition":{"x":13448.454145483884,"y":41055.1750223887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9d53e819-26a4-4e2d-999c-8c68a079a7ed","savedPayload":{"position":{"x":13448.454145483884,"y":41055.1750223887},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"openInterestDeviation","config":"{\n \"codeName\": \"openInterestDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.openInterestDeviation)) {\nvariable.openInterestDeviation\n}\nelse {\nvariable.openInterestDeviation = 1\n}","project":"Superalgos","id":"1a1bba7d-2ea4-452c-980a-885220669585","savedPayload":{"position":{"x":13565.779994264058,"y":40907.02177129943},"targetPosition":{"x":13542.314824508023,"y":41055.1750223887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"78f159de-c0d7-4373-93a1-645e6791fdfa","savedPayload":{"position":{"x":13542.314824508023,"y":41055.1750223887},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"a1e299c4-fed7-4543-9d78-5697aef59e84","savedPayload":{"position":{"x":13486.234055866944,"y":41521.19242596629},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"EDIT TOP LINES HERE TO CHANGE PERIODS","code":"// The Average VS Average Oscillator\n\n/* The Average VS Average Oscillator can be used to recognize changes between a fast average ('fastPeriod') and a slow average ('slowPeriod'). It measures 'Price Action', 'Volume', and a so called 'Open Interest'.\n'Bull Price Action' and 'Bear Price Action' is defined by the amount between the candle close and max and min.\n'Bull Volume' and 'Bear Volume' is divided using the price action.\n'Open Interest' is based upon the statement where:\nBull Candle and Volume Increase = Bull Interest\nBull Candle and Volume Decrease = Bear Interest\nBear Candle and Volume Increase = Bear Interest\nBear Candle and Volume Decrease = Bull Interest */\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n/* Loop code */\n\n// User defined lengths of the used periods\n\nlet fastPeriod = 5 // Change this number to the period of your choice (must be less than 'slowPeriod')\nlet slowPeriod = 21 // Change this number to the period of your choice (must be greater than 'fastPeriod')\nlet periodMultiplier = 3 // The 'slowPeriod' is muliplied by the 'periodMultiplier to create the \"long term\" trend\nlet fastBoost = 1.00 // '1.00' equals 'no extra boost' to your 'fastPeriod' where as '1.23' would boost the value by 23%\nlet gravity = 0 // '0' equals 'no gravity' (pullback towards midline ('slowPeriod'))\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring variables used\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \nlet volCandle = record.current\nlet volume = getElement('volumes', volCandle)\nlet totalVolume = volume.buy + volume.sell\nlet totalRange = candle.max - candle.min\nlet multipliedFast = fastPeriod * periodMultiplier\nlet multipliedSlow = slowPeriod * periodMultiplier\n\nif ( candle.close > candle.open ) { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\nelse { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Volume Difference'\n\nvariable.previousCurrentVolume.push(totalVolume)\nif (variable.previousCurrentVolume.length > 2) {\n variable.previousCurrentVolume.splice(0, 1)\n}\n\nif (variable.previousCurrentVolume[1] === 'undefined') {\n variable.positiveVolumeDifference = 0.01\n}\nelse {\n if (variable.previousCurrentVolume[variable.previousCurrentVolume.max] > variable.previousCurrentVolume[0]) {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[1] - variable.previousCurrentVolume[0]) \n }\n else {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[0] - variable.previousCurrentVolume[1])\n }\n}\n\nvariable.bullVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bullPriceRange / totalRange)\nvariable.bearVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bearPriceRange / totalRange)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Open Interest'\n// Converting values to percentages due to the differences of range and volume (range might be in decimals while volume often is in thousands)\n\nif ( candle.close > candle.open && variable.previousCurrentVolume[1] > variable.previousCurrentVolume[0] ) { // Candle UP & Volume UP, Bullish Interest\n variable.openInterest = 1 + ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close < candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle DOWN & Volume DOWN, Bullish Interest\n variable.openInterest = 1 + ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close > candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle UP & Volume DOWN, Bearish Interest\n variable.openInterest = 1 - ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse { // Candle DOWN & Volume UP, Bearish Interest\n variable.openInterest = 1 - ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Saving to arrays\n\nvariable.savedCandleClose.push(candle.close)\nif (variable.savedCandleClose.length > multipliedSlow) {\n variable.savedCandleClose.splice(0, 1)\n}\n\nvariable.savedTotalRange.push(totalRange)\nif (variable.savedTotalRange.length > multipliedSlow) {\n variable.savedTotalRange.splice(0, 1)\n}\n\nvariable.savedBullPriceRange.push(variable.bullPriceRange)\nif (variable.savedBullPriceRange.length > multipliedSlow) {\n variable.savedBullPriceRange.splice(0, 1)\n}\n\nvariable.savedTotalVolume.push(totalVolume)\nif (variable.savedTotalVolume.length > multipliedSlow) {\n variable.savedTotalVolume.splice(0, 1)\n}\n\nvariable.savedOpenInterest.push(variable.openInterest)\nif (variable.savedOpenInterest.length > multipliedSlow) {\n variable.savedOpenInterest.splice(0, 1)\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Calling SMA functions\n\nvariable.smaMultipliedFastCandleClose = calculateSMA(variable.savedCandleClose, multipliedFast)\nvariable.smaSlowCandleClose = calculateSMA(variable.savedCandleClose, slowPeriod)\nvariable.smaLongTermCandleClose = calculateSMA(variable.savedCandleClose, multipliedSlow)\n\nvariable.smaFastTotalRange = calculateSMA(variable.savedTotalRange, fastPeriod)\nvariable.smaSlowTotalRange = calculateSMA(variable.savedTotalRange, slowPeriod)\nvariable.smaLongTermRange = calculateSMA(variable.savedTotalRange, multipliedSlow)\n\nvariable.smaFastBullPriceRange = calculateSMA(variable.savedBullPriceRange, fastPeriod)\nvariable.smaSlowBullPriceRange = calculateSMA(variable.savedBullPriceRange, slowPeriod)\n\nvariable.smaFastTotalVolume = calculateSMA(variable.savedTotalVolume, fastPeriod)\nvariable.smaLongTermTotalVolume = calculateSMA(variable.savedTotalVolume, multipliedSlow)\n\nvariable.smaFastOpenInterest = calculateSMA(variable.savedOpenInterest, fastPeriod)\nvariable.smaSlowOpenInterest = calculateSMA(variable.savedOpenInterest, slowPeriod)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Creating the SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calculation\n if (src.length < periods) { return 0 }\n \n // Initialize sum variable\n let sum = 0 \n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring record variables by comparing 'fastPeriod' values with 'slowPeriod' values, also applying 'fastBoost' and 'gravity'\n\nvariable.fastPriceRange = variable.smaFastTotalRange\nvariable.slowPriceRange = variable.smaSlowTotalRange\nvariable.longTermPriceRange = variable.smaLongTermRange\n\nvariable.bullPriceDeviation = ((((variable.smaFastBullPriceRange * fastBoost) + (variable.smaSlowBullPriceRange * gravity)) / (gravity + 1)) / variable.slowPriceRange) * 2\n\nvariable.volumeDeviation = variable.smaFastTotalVolume / variable.smaLongTermTotalVolume\n\nvariable.openInterestDeviation = ((((variable.smaFastOpenInterest * fastBoost) + (variable.smaSlowOpenInterest * gravity)) / (gravity + 1)) / variable.smaSlowOpenInterest)\n\nvariable.smaPrice = variable.smaMultipliedFastCandleClose / variable.smaLongTermCandleClose\n\n// CJ.","project":"Superalgos","id":"7e403f54-4a96-4d44-b242-bbbf242c3114","savedPayload":{"position":{"x":13686.245899592052,"y":41306.56742651631},"targetPosition":{"x":13763.960495737749,"y":41369.499465621295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5dd4bc88-e9e8-461e-9c87-03c0aeb5f14a","savedPayload":{"position":{"x":13763.960495737749,"y":41369.499465621295},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 6 arrays \n\nvariable.previousCurrentVolume = []\nvariable.savedTotalRange = []\nvariable.savedBullPriceRange = [] \nvariable.savedTotalVolume = [] \nvariable.savedOpenInterest = [] \nvariable.savedCandleClose = [] ","project":"Superalgos","id":"562a1a92-04fd-4126-b3cc-219d21d96607","savedPayload":{"position":{"x":13790.940402569968,"y":41230.50241765447},"targetPosition":{"x":13826.777197524498,"y":41323.86046030419},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"85dd9771-10b0-492c-ace8-0f18fc14d143","savedPayload":{"position":{"x":13826.777197524498,"y":41323.86046030419},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"159c2cf8-383f-4228-9ad5-bc266cd18d5c","savedPayload":{"position":{"x":13880.532389956294,"y":41463.89752427877},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"371f636a-012c-4fb8-bf61-c83be358a508","savedPayload":{"position":{"x":14056.867965644036,"y":41706.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Average VS Average","id":"60771858-6287-419f-b6db-6ab6166063ba"}}}],"id":"3df48abc-f2a5-48ca-bd27-89913fdc0812","savedPayload":{"position":{"x":14356.867965644036,"y":41706.60262259126},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"plotters":[{"type":"Plotter","name":"ARPS Fast Plotter","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS","config":"{\n \"codeName\": \"ARPS-Fast\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"1216597f-916f-40c3-b1cf-9795d7516eb9","savedPayload":{"position":{"x":16921.752452292843,"y":42034.291126365046},"targetPosition":{"x":16621.886722607793,"y":42025.316486514224},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"23be71f9-d898-4182-8fdf-b437ee15d96a","savedPayload":{"position":{"x":16621.886722607793,"y":42025.316486514224},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"96946ddb-82c4-4ded-a55f-f72a64f8b6d0","savedPayload":{"position":{"x":16854.572466325473,"y":42292.727316933786},"targetPosition":{"x":16588.296729624104,"y":42154.534581798594},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0a02c972-ecf7-4263-b396-7ec44323d68b","savedPayload":{"position":{"x":16588.296729624104,"y":42154.534581798594},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"5f7ae8c1-7d37-4d18-b40c-7f65d33a617e","savedPayload":{"position":{"x":16681.914129735487,"y":42496.42197547013},"targetPosition":{"x":16501.967561329115,"y":42256.38191106677},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0958d221-456d-414b-b383-e6fbec8df430","savedPayload":{"position":{"x":16501.967561329115,"y":42256.38191106677},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"0fa59969-0560-4070-8569-674718ff52e5","savedPayload":{"position":{"x":16437.974543600074,"y":42605.03087669991},"targetPosition":{"x":16379.997768261406,"y":42310.686361681655},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bcc803c6-3d10-48dd-82f2-63603a7c3c97","savedPayload":{"position":{"x":16379.997768261406,"y":42310.686361681655},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"d812fcd7-98e8-4c00-a7b3-9711dc93ba86","savedPayload":{"position":{"x":16171.068934676035,"y":42597.042695733806},"targetPosition":{"x":16246.544963799388,"y":42306.69227119861},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c591ce36-7a4f-4ff2-be7c-48e6e7786502","savedPayload":{"position":{"x":16246.544963799388,"y":42306.69227119861},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"92d970a0-e07c-4958-ab07-f4d968d1bf33","savedPayload":{"position":{"x":15934.061232193262,"y":42474.03958978076},"targetPosition":{"x":16128.041112558001,"y":42245.19071822209},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"221a1676-98f3-4175-a301-4f4e85abfe4f","savedPayload":{"position":{"x":16128.041112558001,"y":42245.19071822209},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8a7b65d5-ae94-4075-98d6-1fb143128c07","savedPayload":{"position":{"x":13941.02099292274,"y":42028.34184666341},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"8a3b9f48-6556-4ffc-8694-44db9d0552e3","savedPayload":{"position":{"x":16464.409913763688,"y":42538.924830358024},"targetPosition":{"x":16301.01820325918,"y":42287.3236599744},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f2b46265-4f40-4572-a023-e95007bcbf2a","savedPayload":{"position":{"x":16301.01820325918,"y":42287.3236599744},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"a24fec7c-4b4e-4533-b40b-fe86bb05a8e6","savedPayload":{"position":{"x":16075.252985509345,"y":42329.16676981091},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"23be71f9-d898-4182-8fdf-b437ee15d96a"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"cfccbef2-3746-43c5-8368-fcd84072eec1","savedPayload":{"position":{"x":15886.025322371046,"y":42199.114200095275},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"0a02c972-ecf7-4263-b396-7ec44323d68b"}}}],"id":"b5e43c46-948c-4f56-bfe5-83ba923a20a5","savedPayload":{"position":{"x":13756.626492754673,"y":42047.72248959077},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d8e0d8e9-27ef-4fab-ac43-23868fea8813","savedPayload":{"position":{"x":15945.654978611015,"y":42542.19511213103},"targetPosition":{"x":15961.355765483899,"y":42242.60625170465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"19197333-4a73-4f74-8d05-de667c8d8bf1","savedPayload":{"position":{"x":15961.355765483899,"y":42242.60625170465},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"afc2f8ff-8082-496f-8106-a1f8379cfd12","savedPayload":{"position":{"x":15754.113104713564,"y":42143.75657318594},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"0958d221-456d-414b-b383-e6fbec8df430"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"1606a418-a639-4cd4-909d-de72d689acf0","savedPayload":{"position":{"x":15677.46769193041,"y":41927.3166044054},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"bcc803c6-3d10-48dd-82f2-63603a7c3c97"}}}],"id":"7b2bf0a5-4eb1-4cf6-bb1e-8b7545691dfa","savedPayload":{"position":{"x":13596.056552356782,"y":41955.017391278285},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"0e69ccc1-020e-47e3-9251-1af8231e41c1","savedPayload":{"position":{"x":15524.051196759618,"y":42239.9243252251},"targetPosition":{"x":15712.847314074568,"y":42006.780536788014},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"af7adcc4-8cd2-408f-8550-e017bdbd7d38","savedPayload":{"position":{"x":15712.847314074568,"y":42006.780536788014},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"5b569cf7-d916-4891-9f48-4ffbd9a07acb","savedPayload":{"position":{"x":15603.286862779038,"y":41804.99528733122},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"c591ce36-7a4f-4ff2-be7c-48e6e7786502"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"1197f1d6-2c5f-4c4f-b478-0ff005c8408c","savedPayload":{"position":{"x":15668.499642952427,"y":41584.84063103597},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"221a1676-98f3-4175-a301-4f4e85abfe4f"}}}],"id":"0dbddbd2-336e-4495-adee-2cb008743b39","savedPayload":{"position":{"x":13520.643431389519,"y":41785.636748350924},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"ab1a9808-3321-487e-a4ee-598cbe1e06e6","savedPayload":{"position":{"x":13819,"y":41754.27820937063},"targetPosition":{"x":13969,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS","config":"{\n \"codeName\": \"ARPS\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"40a7c8ec-adfa-4319-afbb-4fdce8d83548","savedPayload":{"position":{"x":13239.444504226558,"y":41234.66296709996},"targetPosition":{"x":13529.222252113279,"y":41157.0172535692},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"485aa9f4-e9cb-4734-883f-8a3f68a2f054","savedPayload":{"position":{"x":13317.090217757315,"y":40944.88521921324},"targetPosition":{"x":13529.222252113279,"y":41157.0172535692},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"9cdae6f2-28fd-47bc-930d-3454aa053de4","savedPayload":{"position":{"x":13529.222252113279,"y":41157.0172535692},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"6d06c410-c7fc-46d9-a935-5125326f4ff6","savedPayload":{"position":{"x":13409.192378864669,"y":40824.85534596463},"targetPosition":{"x":13669,"y":40974.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"567e7a98-a673-46ad-9b48-64c55f4e2c91","savedPayload":{"position":{"x":13669,"y":40674.85534596463},"targetPosition":{"x":13669,"y":40974.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"da3f2ea2-6452-4f7a-afd0-c91bb3915956","savedPayload":{"position":{"x":13669,"y":40974.85534596463},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"8bb34797-b438-46b7-98ac-13626abeb3d9","savedPayload":{"position":{"x":13819,"y":40655.10747132652},"targetPosition":{"x":13896.645713530756,"y":40944.88521921324},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"fc5e8a98-9891-4c4e-aaf4-3b1d485c1d0d","savedPayload":{"position":{"x":14108.77774788672,"y":40732.753184857276},"targetPosition":{"x":13896.645713530756,"y":40944.88521921324},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e738ec96-c711-4b1d-9689-7bbe923b84db","savedPayload":{"position":{"x":13896.645713530756,"y":40944.88521921324},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"97906f34-67ef-438b-85a7-59cebfd1dcfb","savedPayload":{"position":{"x":13819,"y":41234.66296709996},"targetPosition":{"x":13969,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2675db9e-a697-4f84-a252-8c27ed423e24","savedPayload":{"position":{"x":13969,"y":41494.470588235294},"targetPosition":{"x":14269,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e9b75238-86e2-4069-8f82-d8884bf729ee","savedPayload":{"position":{"x":14269,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Chaikin Oscillator Plotter","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.zeroLine","project":"Superalgos","id":"fec8363f-45ef-4e43-850a-4102ae1d1f62","savedPayload":{"position":{"x":15743.934675239096,"y":41002.99424592844},"targetPosition":{"x":15977.078463676187,"y":40814.19812861349},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b4d7a68b-446d-4aab-938b-3da564ec607d","savedPayload":{"position":{"x":15977.078463676187,"y":40814.19812861349},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.zeroLine","project":"Superalgos","id":"3db966a2-1491-4758-a29f-e6caedcf2208","savedPayload":{"position":{"x":15611.044531260533,"y":40656.803585044305},"targetPosition":{"x":15910.633391686906,"y":40641.10279817142},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"013e2783-f200-4b83-b914-91aefd6e7e6f","savedPayload":{"position":{"x":15910.633391686906,"y":40641.10279817142},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.chaikinOscillator","project":"Superalgos","id":"78359bae-9317-4916-a89f-d41d00a24627","savedPayload":{"position":{"x":15707.019911346026,"y":40298.61859028952},"targetPosition":{"x":15958.621081729652,"y":40462.010300794034},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b159f5cc-42a5-498f-a699-f033248a7eb1","savedPayload":{"position":{"x":15958.621081729652,"y":40462.010300794034},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.chaikinOscillator","project":"Superalgos","id":"2384e88c-6e7a-4635-bb62-361dd0edda7d","savedPayload":{"position":{"x":15995.201482386099,"y":40065.25375540022},"targetPosition":{"x":16102.711867249689,"y":40345.32788334938},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"00cac505-e6ac-44b5-bc76-1e88a17ebd88","savedPayload":{"position":{"x":16102.711867249689,"y":40345.32788334938},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2fba905c-acdb-4217-ba62-2e762b1ddeec","savedPayload":{"position":{"x":16210.222252113279,"y":40625.40201129854},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d2054636-c85e-49df-ab90-313851dfcc4c","savedPayload":{"position":{"x":15770.444504226558,"y":40287.94867663245},"targetPosition":{"x":16060.222252113279,"y":40365.594390163205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d3277379-9eb1-4fca-b134-c4dcdf45d532","savedPayload":{"position":{"x":16060.222252113279,"y":40365.594390163205},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"3b89ce9b-df0f-4fb3-b181-deb5d6926262","savedPayload":{"position":{"x":16200,"y":40183.43248255863},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"b4d7a68b-446d-4aab-938b-3da564ec607d"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"93d7041c-5f20-4b85-9f7a-f16d6427d7b2","savedPayload":{"position":{"x":16427.645713530757,"y":40153.46235580724},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"013e2783-f200-4b83-b914-91aefd6e7e6f"}}}],"id":"bad71c42-7ad3-41df-9634-9599e0cd59c7","savedPayload":{"position":{"x":16350,"y":40443.24010369396},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"Chaikin Oscillator","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d35e45c5-146b-41a2-8973-06c7dabc010b","savedPayload":{"position":{"x":16277.645713530756,"y":39893.65473467191},"targetPosition":{"x":16427.645713530757,"y":40153.46235580724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d746e2c7-aae0-4c83-a1a2-23a1d779173c","savedPayload":{"position":{"x":16427.645713530757,"y":40153.46235580724},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Chaikin Oscillator Begin","project":"Superalgos","id":"cc9ee8d7-5b93-4c3b-a700-db3776fbe24a","savedPayload":{"position":{"x":16655.29142706151,"y":40123.49222905585},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator Begin","id":"b159f5cc-42a5-498f-a699-f033248a7eb1"}}},{"type":"Polygon Vertex","name":"Chaikin Oscillator End","project":"Superalgos","id":"e9007c32-1519-497a-bed3-7eaa3f60ccff","savedPayload":{"position":{"x":16837.453334666086,"y":40263.269976942574},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator End","id":"00cac505-e6ac-44b5-bc76-1e88a17ebd88"}}}],"id":"78c2a948-2c47-40c9-89d8-00d7992cb17c","savedPayload":{"position":{"x":16577.645713530757,"y":40413.269976942574},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"6f0e43ac-96e8-490f-9d08-8c7489a6614c","savedPayload":{"position":{"x":16500,"y":40703.047724829295},"targetPosition":{"x":16650,"y":40962.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"653018cc-a18a-4370-a6c5-e0ad879b2c2f","savedPayload":{"position":{"x":16650,"y":40962.85534596463},"targetPosition":{"x":16800,"y":41222.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"412c32ee-724a-4b58-9fef-58ecf975de8b","savedPayload":{"position":{"x":14356.867965644036,"y":41282.33855387933},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Slow Plotter","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"ca8a3ebb-25b0-4359-b3c5-218fc7ee69a0","savedPayload":{"position":{"x":16845.752452292843,"y":42258.791126365046},"targetPosition":{"x":16545.886722607793,"y":42249.816486514224},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e5da7299-927f-46e1-95a0-18230e59af0e","savedPayload":{"position":{"x":16545.886722607793,"y":42249.816486514224},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"f9baacc0-6c94-421b-8a65-629e37e19e7d","savedPayload":{"position":{"x":16778.572466325473,"y":42517.227316933786},"targetPosition":{"x":16512.296729624104,"y":42379.034581798594},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1fa7c445-e500-44ac-94d2-1f4f8b4a4a32","savedPayload":{"position":{"x":16512.296729624104,"y":42379.034581798594},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"89b91ab8-fd0b-4f22-885e-968f84dba9db","savedPayload":{"position":{"x":16605.914129735487,"y":42720.92197547013},"targetPosition":{"x":16425.96756132911,"y":42480.88191106677},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"3ec07cce-c6fd-4e38-9581-20665a1f42e3","savedPayload":{"position":{"x":16425.96756132911,"y":42480.88191106677},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"6bff0f0a-5220-41a3-b785-0c3fdc0d7c22","savedPayload":{"position":{"x":16361.974543600072,"y":42829.53087669991},"targetPosition":{"x":16303.997768261404,"y":42535.186361681655},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b9fcdbe-6783-4719-b3ca-a8811b2ef7e6","savedPayload":{"position":{"x":16303.997768261404,"y":42535.186361681655},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"2a45e116-9295-46fe-beb5-e97bb88fa18f","savedPayload":{"position":{"x":16095.068934676034,"y":42821.542695733806},"targetPosition":{"x":16170.544963799386,"y":42531.19227119861},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b1673c67-03d9-4f80-b7d7-6ea05d917b9a","savedPayload":{"position":{"x":16170.544963799386,"y":42531.19227119861},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"9b122b4f-ea2b-426b-8b72-e57e62688280","savedPayload":{"position":{"x":15858.06123219326,"y":42698.53958978076},"targetPosition":{"x":16052.041112558,"y":42469.69071822209},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1a63a717-1978-47a8-9b3d-50995f7d77a9","savedPayload":{"position":{"x":16052.041112558,"y":42469.69071822209},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c574a116-3471-454e-aa91-939ea988d761","savedPayload":{"position":{"x":14635.54422723201,"y":40672.91838677305},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"722a1147-5e6d-4b23-8f45-61450a7d0b00","savedPayload":{"position":{"x":16388.409913763688,"y":42763.424830358024},"targetPosition":{"x":16225.018203259178,"y":42511.8236599744},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"4383c9dd-82d5-494b-aef3-5df2cc85d159","savedPayload":{"position":{"x":16225.018203259178,"y":42511.8236599744},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"1e9c722a-92cc-4189-836f-53ad2dc7938f","savedPayload":{"position":{"x":15999.252985509343,"y":42553.66676981091},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"e5da7299-927f-46e1-95a0-18230e59af0e"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"2f93dabf-aae9-44e0-9273-8124fcdc3dab","savedPayload":{"position":{"x":15810.025322371044,"y":42423.614200095275},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"1fa7c445-e500-44ac-94d2-1f4f8b4a4a32"}}}],"id":"2490ae4c-0fce-4ad1-85bc-a651044a408c","savedPayload":{"position":{"x":14752.226644676664,"y":40528.82760125302},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"4a8be682-30e9-4595-8fd7-a7bdd5275af8","savedPayload":{"position":{"x":15869.654978611014,"y":42766.69511213103},"targetPosition":{"x":15885.355765483897,"y":42467.10625170465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"106b5fd8-64f3-4731-96e3-641dddb9bb06","savedPayload":{"position":{"x":15885.355765483897,"y":42467.10625170465},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"1e039cea-279e-4319-a562-65d2b3e42415","savedPayload":{"position":{"x":15678.113104713562,"y":42368.25657318594},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"3ec07cce-c6fd-4e38-9581-20665a1f42e3"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"667f6ce6-e9c3-4485-89bd-270311441baf","savedPayload":{"position":{"x":15601.467691930407,"y":42151.8166044054},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"1b9fcdbe-6783-4719-b3ca-a8811b2ef7e6"}}}],"id":"0f06b5f2-e742-4520-8e0e-6a7e9bd4974e","savedPayload":{"position":{"x":14931.319142054055,"y":40480.83991121027},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"153aa0a3-9042-429c-9eae-dc5385217116","savedPayload":{"position":{"x":15448.051196759616,"y":42464.4243252251},"targetPosition":{"x":15636.847314074566,"y":42231.280536788014},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f031e2cb-6fb6-469d-8baa-bcfe24dec1c3","savedPayload":{"position":{"x":15636.847314074566,"y":42231.280536788014},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"03a063b9-6203-4384-b89e-e85341b0cb24","savedPayload":{"position":{"x":15527.286862779036,"y":42029.49528733122},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"b1673c67-03d9-4f80-b7d7-6ea05d917b9a"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"2507628c-b9e6-4103-9c94-21abc3489762","savedPayload":{"position":{"x":15592.499642952425,"y":41809.34063103597},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"1a63a717-1978-47a8-9b3d-50995f7d77a9"}}}],"id":"7c0e4100-b3c1-4e60-85f1-1d9e1bd6f7fd","savedPayload":{"position":{"x":15104.414472496122,"y":40547.284983199555},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"aeebf45e-fe48-4377-a483-c9c67690a62f","savedPayload":{"position":{"x":14915.618355181172,"y":40780.428771636645},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS","config":"{\n \"codeName\": \"ARPS\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"61766652-706a-4bb9-87ef-2d6e6943d853","savedPayload":{"position":{"x":15692.84943773398,"y":40738.04461191879},"targetPosition":{"x":15542.84943773398,"y":40997.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"51875264-c8ee-4839-aa4d-1b9b71d891ff","savedPayload":{"position":{"x":15842.84943773398,"y":40997.852233054124},"targetPosition":{"x":15542.84943773398,"y":40997.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b4f7f01-5b42-4954-8668-3cbda5b77063","savedPayload":{"position":{"x":15542.84943773398,"y":40997.852233054124},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"e9c52716-c5f2-4624-ba6e-c173c7f7dbfd","savedPayload":{"position":{"x":15862.59731237209,"y":41147.852233054124},"targetPosition":{"x":15572.81956448537,"y":41225.49794658488},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"7feaef19-3ea1-4124-8aa4-afd75c5816f1","savedPayload":{"position":{"x":15784.951598841333,"y":41437.629980940845},"targetPosition":{"x":15572.81956448537,"y":41225.49794658488},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bce58d87-f0fc-4515-ab47-1d5d57162bac","savedPayload":{"position":{"x":15572.81956448537,"y":41225.49794658488},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"e00cdf0d-5b55-4ce1-a960-bae254b568dd","savedPayload":{"position":{"x":15692.84943773398,"y":41557.65985418946},"targetPosition":{"x":15433.041816598648,"y":41407.65985418946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"f7999c40-89bc-4c73-9ea5-1b2266814a5c","savedPayload":{"position":{"x":15433.041816598648,"y":41707.65985418946},"targetPosition":{"x":15433.041816598648,"y":41407.65985418946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"dd112929-5166-4ac7-9c61-9158e3eab9e0","savedPayload":{"position":{"x":15433.041816598648,"y":41407.65985418946},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1e96ebb8-5d70-440d-977f-1781f746f31a","savedPayload":{"position":{"x":15283.041816598648,"y":41147.852233054124},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ba1f7fe7-29a3-4cf2-b185-dc2c65e5cc5a","savedPayload":{"position":{"x":14993.264068711927,"y":41070.206519523366},"targetPosition":{"x":14781.132034355964,"y":41282.33855387933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"75c554ed-b9fd-4fb9-9f27-7d6e5e665f8a","savedPayload":{"position":{"x":14569,"y":41194.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Average VS Average Plotter","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = 1","project":"Superalgos","id":"5ebd08dc-c6b9-4429-92c5-b44e86727d6a","savedPayload":{"position":{"x":14886.480951457786,"y":41080.62920696757},"targetPosition":{"x":15113.94976613913,"y":40692.35361109852},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9","savedPayload":{"position":{"x":15113.94976613913,"y":40692.35361109852},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = 1","project":"Superalgos","id":"246941f4-3c18-4ca4-be0f-e8cef636bec1","savedPayload":{"position":{"x":14686.129369247508,"y":40921.00268583042},"targetPosition":{"x":15013.773975033992,"y":40612.54035052995},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c575e8b4-3491-4533-be08-fae19636edd9","savedPayload":{"position":{"x":15013.773975033992,"y":40612.54035052995},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.bullPriceDeviation","project":"Superalgos","id":"e7e97620-5c89-4806-8855-1118189cca8c","savedPayload":{"position":{"x":14538.865421803868,"y":40711.396596873456},"targetPosition":{"x":14940.142001312171,"y":40507.737306051466},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5856cd48-be9d-43a4-ab20-5215f4d8008f","savedPayload":{"position":{"x":14940.142001312171,"y":40507.737306051466},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.bullPriceDeviation","project":"Superalgos","id":"1fea2d4e-6680-48ab-b7c8-385f26b473d7","savedPayload":{"position":{"x":14456.61955833634,"y":40468.79197884859},"targetPosition":{"x":14899.019069578408,"y":40386.43499703903},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0f7c9019-cf97-455b-997b-23bb7fd5ee8d","savedPayload":{"position":{"x":14899.019069578408,"y":40386.43499703903},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.volumeDeviation","project":"Superalgos","id":"7bd64bdc-26e2-473e-b6b4-dfd9a1b90395","savedPayload":{"position":{"x":14446.054849568074,"y":40212.84321508295},"targetPosition":{"x":14893.736715194274,"y":40258.46061515621},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff","savedPayload":{"position":{"x":14893.736715194274,"y":40258.46061515621},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.volumeDeviation","project":"Superalgos","id":"da79b97b-1844-4fda-89ee-ad427795597e","savedPayload":{"position":{"x":14508.027185372732,"y":39964.285752230935},"targetPosition":{"x":14924.722883096603,"y":40134.181883730205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4","savedPayload":{"position":{"x":14924.722883096603,"y":40134.181883730205},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.openInterestDeviation","project":"Superalgos","id":"d1dea870-5cc2-40ec-a697-16f607c5d976","savedPayload":{"position":{"x":14637.515935667096,"y":39743.25623770467},"targetPosition":{"x":14989.467258243785,"y":40023.66712646707},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"01f5ed3c-22df-4a5e-bc9a-1c1bcd82e187","savedPayload":{"position":{"x":14989.467258243785,"y":40023.66712646707},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.openInterestDeviation","project":"Superalgos","id":"9516a25e-3b91-4d82-a02f-6ec800fdfdff","savedPayload":{"position":{"x":14824.030692001568,"y":39567.661168257924},"targetPosition":{"x":15082.724636411021,"y":39935.8695917437},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5f18a8ed-6d3a-4e97-b2c7-8833ae328ee0","savedPayload":{"position":{"x":15082.724636411021,"y":39935.8695917437},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.smaPrice","project":"Superalgos","id":"de1c3212-9782-4dd2-b7a6-6d1215fcaa4f","savedPayload":{"position":{"x":15052.461138063893,"y":39451.72621211319},"targetPosition":{"x":15196.939859442184,"y":39877.902113671335},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ae121f69-414a-4593-bee4-3f42c4855e75","savedPayload":{"position":{"x":15196.939859442184,"y":39877.902113671335},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.smaPrice","project":"Superalgos","id":"8c70536b-5484-4c7f-a7d9-1a4b83f180f4","savedPayload":{"position":{"x":15304.301197642275,"y":39404.84372992559},"targetPosition":{"x":15322.859889231375,"y":39854.46087257753},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b413b15-e479-4d18-9c8e-0cc067c791eb","savedPayload":{"position":{"x":15322.859889231375,"y":39854.46087257753},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"61cb4958-a145-4e5b-ac3d-976868a2bbb3","savedPayload":{"position":{"x":15015.217885284577,"y":40450.23598100091},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"a2aa7fc6-9333-44d9-a272-79da7527502a","savedPayload":{"position":{"x":14967.529071742714,"y":40194.74209150929},"targetPosition":{"x":15267.520679261095,"y":40196.986065336605},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"cef91315-4506-4374-83a2-c899fcdec3a3","savedPayload":{"position":{"x":15267.520679261095,"y":40196.986065336605},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"b8cb8331-a6ec-4693-81e5-0c518f8d3bf7","savedPayload":{"position":{"x":15356.972915914279,"y":39985.51721007852},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"5fb2e9a0-5ae9-4132-9309-4ed517d26111","savedPayload":{"position":{"x":15569.756260606797,"y":39899.23843164554},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}}],"id":"cca59d3d-d290-4534-802f-8b20224875d7","savedPayload":{"position":{"x":15179.249380243593,"y":40559.21607573988},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice > record.previous.smaPrice","project":"Superalgos","id":"f3e0632e-6cf2-4f0b-bef7-82b15c1c4795","savedPayload":{"position":{"x":15310.005105837628,"y":40240.27137909361},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"8ce4673b-02f7-4fdd-a41a-68bd3603eb11","savedPayload":{"position":{"x":15009.10307759985,"y":40076.377090912705},"targetPosition":{"x":15305.40957977839,"y":40123.30743042477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"b0533485-c84c-492b-be01-f5da1e7acfa0","savedPayload":{"position":{"x":15305.40957977839,"y":40123.30743042477},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"4a3ebec3-46cf-424b-8b19-3246dcd527b6","savedPayload":{"position":{"x":15090.131983344474,"y":39856.73863110726},"targetPosition":{"x":15345.924032650702,"y":40013.48820052205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"968cf63e-2566-4697-92c2-4e9a01de083a","savedPayload":{"position":{"x":15345.924032650702,"y":40013.48820052205},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"960b6798-dc4b-4ccf-a1d2-8d114b228ba4","savedPayload":{"position":{"x":15425.380506269188,"y":39927.53267162435},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"ae121f69-414a-4593-bee4-3f42c4855e75"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"ec3a86be-3906-4395-ad66-22974b63e702","savedPayload":{"position":{"x":15531.68247280016,"y":39878.52679381753},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"1b413b15-e479-4d18-9c8e-0cc067c791eb"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"47505d15-f5cd-4eed-a2ca-0e19e1fd5425","savedPayload":{"position":{"x":15648.646421469,"y":39873.93126775829},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"a95edd6e-9ac7-4c4b-8d44-2ea5d4c91126","savedPayload":{"position":{"x":15758.465651371716,"y":39914.44572063061},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}}],"id":"0b45de42-16c8-4845-9634-0c4594a848a5","savedPayload":{"position":{"x":15283.041816598647,"y":40568.29673728068},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice < record.previous.smaPrice","project":"Superalgos","id":"ba7bc4d2-ea9d-46e5-8a46-4076b973082d","savedPayload":{"position":{"x":15397.288894196598,"y":40090.60339533746},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"c397754e-7f7f-4101-85bc-ce03e0560cd1","savedPayload":{"position":{"x":15170.588626615936,"y":39833.67858732003},"targetPosition":{"x":15432.974538757755,"y":39979.12147339393},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f869822a-1175-4ca9-b1ab-0eb6c8e8aa21","savedPayload":{"position":{"x":15432.974538757755,"y":39979.12147339393},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"45046251-89ef-4e4a-a6ad-508940e81d8b","savedPayload":{"position":{"x":15321.851668917003,"y":39654.99946535638},"targetPosition":{"x":15508.606059908288,"y":39889.7819124121},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d72f0442-35cd-4291-9ed0-2d18974d8622","savedPayload":{"position":{"x":15508.606059908288,"y":39889.7819124121},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"1de42509-51b7-4db5-bb4b-ec99f020f67f","savedPayload":{"position":{"x":15612.669244154475,"y":39836.18585068633},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"ae121f69-414a-4593-bee4-3f42c4855e75"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"086e31ca-712a-4a76-bfde-85f94a0c1f3d","savedPayload":{"position":{"x":15729.321415029946,"y":39826.49280276485},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"1b413b15-e479-4d18-9c8e-0cc067c791eb"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"d2474336-018f-4a72-b944-8cca376adeab","savedPayload":{"position":{"x":15840.803336973475,"y":39862.178447326005},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"61bd3a59-9a0b-45bf-8541-69e9cce47c5b","savedPayload":{"position":{"x":15930.142897955298,"y":39937.80996847654},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}}],"id":"7c193813-cccc-44d2-aa9d-0896829f042b","savedPayload":{"position":{"x":15377.469033973204,"y":40612.3288718807},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation > record.previous.volumeDeviation","project":"Superalgos","id":"7d0a809e-062d-422f-8b7d-10485a9f795b","savedPayload":{"position":{"x":15538.426213757815,"y":39964.97108377715},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"e43653a6-3d17-4654-b54a-df888f3c6314","savedPayload":{"position":{"x":15458.518676912643,"y":39619.62199501265},"targetPosition":{"x":15628.748638340277,"y":39866.64782409201},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"0d23723f-0ff9-45ad-87df-48ea3e1c2303","savedPayload":{"position":{"x":15628.748638340277,"y":39866.64782409201},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"31da194c-7e54-492e-ad59-4de79fd948f2","savedPayload":{"position":{"x":15752.787194516952,"y":39817.25105942903},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"610ad563-a4f0-4056-b455-f8769a6b14c5","savedPayload":{"position":{"x":15885.974525003989,"y":39826.56442484125},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"88f8f21a-a2a3-4495-b6b5-87535eba5707","savedPayload":{"position":{"x":16001.931245563013,"y":39892.743294087864},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"a5449c88-9bfc-4dea-b10b-7d52c7033224","savedPayload":{"position":{"x":16077.690705571462,"y":40002.68013048401},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff"}}}],"id":"471faeec-673f-4e1b-b09e-876a5a47fc26","savedPayload":{"position":{"x":15451.141716354588,"y":40686.00155426209},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation < record.previous.volumeDeviation","project":"Superalgos","id":"d6e67762-8e26-49eb-9dfb-76e9f91ce637","savedPayload":{"position":{"x":15464.277178666107,"y":40013.38730342399},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"6a4f75ce-c32a-4c6d-abf4-ca5930321ad4","savedPayload":{"position":{"x":15325.614376933983,"y":39687.160641468035},"targetPosition":{"x":15536.15374779918,"y":39900.87347055344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8d9386bd-34ff-4935-9ff4-bf8c61aaa81e","savedPayload":{"position":{"x":15536.15374779918,"y":39900.87347055344},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"95297404-bf72-4524-b035-271c2077d97a","savedPayload":{"position":{"x":15649.730221428039,"y":39830.68808449909},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"af1b8269-e003-490a-8615-db6ee76fc758","savedPayload":{"position":{"x":15782.511386026452,"y":39816.73222173629},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"6fd2d967-3262-4e23-807a-55ea30878977","savedPayload":{"position":{"x":15908.198303491583,"y":39861.77001204262},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"4cdb7b68-9c6b-42ac-be3a-6de38cd9674f","savedPayload":{"position":{"x":16001.89713837058,"y":39956.88116869569},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff"}}}],"id":"0f21f203-c9c7-49b9-a385-2c35777d29f7","savedPayload":{"position":{"x":15495.173850954612,"y":40780.428771636645},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"openInterestDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 2,\n 7\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"a4cb8a9f-a8b0-4a8a-aec3-943acf806a1a","savedPayload":{"position":{"x":15975.977724920001,"y":39597.23231105389},"targetPosition":{"x":15981.213446851187,"y":39897.18661960081},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"3713f189-0b41-47c9-9c2e-298c552add2a","savedPayload":{"position":{"x":15981.213446851187,"y":39897.18661960081},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"openInterestDeviation Begin","project":"Superalgos","id":"350b9484-0724-4be2-874e-ca36e33624cd","savedPayload":{"position":{"x":16194.84667992007,"y":39981.33898804614},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation Begin","id":"01f5ed3c-22df-4a5e-bc9a-1c1bcd82e187"}}},{"type":"Polygon Vertex","name":"openInterestDeviation End","project":"Superalgos","id":"faa57ea2-d4ae-4e99-a3c5-8f4c81b4a34a","savedPayload":{"position":{"x":16286.40347732929,"y":40191.90520621655},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation End","id":"5f18a8ed-6d3a-4e97-b2c7-8833ae328ee0"}}}],"id":"7f7d3fc6-4d2a-4089-bcf7-a16c360c5d22","savedPayload":{"position":{"x":15504.254512495414,"y":40884.2212079917},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"bullPriceDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 3,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"c4087104-30ad-4af1-8803-59af51da41f3","savedPayload":{"position":{"x":16243.030764208715,"y":39714.12037885301},"targetPosition":{"x":16145.36031787157,"y":39997.77595153281},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d8c419ea-638b-43bc-923e-eed6ed4f37ee","savedPayload":{"position":{"x":16145.36031787157,"y":39997.77595153281},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"bullPriceDeviation Begin","project":"Superalgos","id":"334d6bde-0a67-4e7e-b0df-3c28eed184b9","savedPayload":{"position":{"x":16317.328085424173,"y":40149.92018017588},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation Begin","id":"5856cd48-be9d-43a4-ab20-5215f4d8008f"}}},{"type":"Polygon Vertex","name":"bullPriceDeviation End","project":"Superalgos","id":"be73fa5c-820b-431b-9eba-a7a4a899335a","savedPayload":{"position":{"x":16331.345444214217,"y":40379.10197054975},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation End","id":"0f7c9019-cf97-455b-997b-23bb7fd5ee8d"}}}],"id":"5d8bc357-8920-4c8f-b491-d7441fbc1116","savedPayload":{"position":{"x":15477.288439178887,"y":40984.85996368961},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"4fab7c9a-d0ea-4a8b-ba5e-b542d1f03aad","savedPayload":{"position":{"x":15205.396103067891,"y":40858.0744851674},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"60771858-6287-419f-b6db-6ab6166063ba","savedPayload":{"position":{"x":14993.264068711927,"y":41070.206519523366},"targetPosition":{"x":14781.132034355964,"y":41282.33855387933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3a455597-8c02-4f2f-acb0-031e12ecc725","savedPayload":{"position":{"x":14781.132034355964,"y":41282.33855387933},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"326278f7-adb0-4a6f-b606-1313b910818a","savedPayload":{"position":{"x":14569,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}} \ No newline at end of file From 0805284d5a1bcfb69f557cb8604918c610f36bbc Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Tue, 9 Mar 2021 12:13:46 +0100 Subject: [PATCH 02/32] Started the "User Examples" docs --- ...trailing-stop-loss-percentage-of-rate.json | 44 ++++++++++++++++++ ...top-loss-risk-of-total-quoted-balance.json | 46 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-001-trailing-stop-loss-percentage-of-rate.json create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-002-trailing-stop-loss-risk-of-total-quoted-balance.json diff --git a/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-001-trailing-stop-loss-percentage-of-rate.json b/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-001-trailing-stop-loss-percentage-of-rate.json new file mode 100644 index 000000000..e371d17ca --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-001-trailing-stop-loss-percentage-of-rate.json @@ -0,0 +1,44 @@ +{ + "topic": "User Examples for Stop Loss ", + "pageNumber": 1, + "type": " Trailing Stop Loss - Percentage of Rate", + "definition": { + "text": "A Trailing Stop Loss tracks the rate and sets the Stop Loss a given distance away from it", + "updated": 1615285882641 + }, + "paragraphs": [ + { + "style": "Note", + "text": "Change the \"trailingStopLoss\" value to what you see fit.", + "updated": 1615286541864 + }, + { + "style": "Subtitle", + "text": "Trailing Stop Loss for a Long Position" + }, + { + "style": "Javascript", + "text": "\nlet trailingStopLoss = 3 // Set the percentage you wish your Trailing Stop Loss to trail\n\nif ( chart.at01min.candle.close * ( 1 - (trailingStopLoss / 100) ) > tradingEngine.tradingCurrent.position.stopLoss.value ) {\nchart.at01min.candle.close * ( 1 - (trailingStopLoss / 100) )\n}\nelse {\ntradingEngine.tradingCurrent.position.stopLoss.value\n}", + "updated": 1615286314820 + }, + { + "style": "Important", + "text": "For a Long Position we want our Stop Loss below the actual rate", + "updated": 1615286643236 + }, + { + "style": "Subtitle", + "text": "Trailing Stop Loss for a Short Position" + }, + { + "style": "Javascript", + "text": "\nlet trailingStopLoss = 3 // Set the percentage you wish your Trailing Stop Loss to trail\n\nif ( chart.at01min.candle.close * ( 1 + (trailingStopLoss / 100) ) > tradingEngine.tradingCurrent.position.stopLoss.value ) {\nchart.at01min.candle.close * ( 1 + (trailingStopLoss / 100) )\n}\nelse {\ntradingEngine.tradingCurrent.position.stopLoss.value\n}", + "updated": 1615286314820 + }, + { + "style": "Important", + "text": "For a Short Position we want our Stop Loss above the actual rate", + "updated": 1615286643236 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-002-trailing-stop-loss-risk-of-total-quoted-balance.json b/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-002-trailing-stop-loss-risk-of-total-quoted-balance.json new file mode 100644 index 000000000..84fe43f85 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/user-examples-for-stop-loss-002-trailing-stop-loss-risk-of-total-quoted-balance.json @@ -0,0 +1,46 @@ +{ + "topic": "User Examples for Stop Loss ", + "pageNumber": 2, + "type": " Trailing Stop Loss - Risk of Total Quoted Balance", + "definition": { + "text": "This Trailing Stop Loss sets the Stop Loss according to the percentage you are willing to risk out of your Total Quoted Balance", + "updated": 1615287509462 + }, + "paragraphs": [ + { + "style": "Note", + "text": "Change the \"riskPercentage\" value to what you see fit", + "updated": 1615288038247 + }, + { + "style": "Title", + "text": "Risk of Total Quoted Balance" + }, + { + "style": "Text", + "text": "The idea is based upon that with each position you take, you only want to risk a certain percentage out of your total balance." + }, + { + "style": "Text", + "text": "Given that you might take several positions, this code sets the stop loss at the point where the loss would be equal to the Risk Percentage out of your Total Quoted Balance." + }, + { + "style": "Subtitle", + "text": "Example for a Long Position" + }, + { + "style": "Javascript", + "text": "\nlet riskPercentage = 2\n\nif ( tradingEngine.tradingCurrent.position.entryTargetRate.value * (1 - (( tradingEngine.tradingCurrent.tradingEpisode.episodeQuotedAsset.balance.value * (riskPercentage / 100)) / tradingEngine.tradingCurrent.strategyOpenStage.stageQuotedAsset.sizeFilled.value)) > tradingEngine.tradingCurrent.position.stopLoss.value ) \n\n{\ntradingEngine.tradingCurrent.position.entryTargetRate.value * (1 - (( tradingEngine.tradingCurrent.tradingEpisode.episodeQuotedAsset.balance.value * (riskPercentage / 100)) / tradingEngine.tradingCurrent.strategyOpenStage.stageQuotedAsset.sizeFilled.value))\n}\n\nelse {\ntradingEngine.tradingCurrent.position.stopLoss.value\n}", + "updated": 1615287799360 + }, + { + "style": "Subtitle", + "text": "Example for a Short Position" + }, + { + "style": "Javascript", + "text": "\nlet riskPercentage = 2\n\nif ( tradingEngine.tradingCurrent.position.entryTargetRate.value * (1 + (( tradingEngine.tradingCurrent.tradingEpisode.episodeQuotedAsset.balance.value * (riskPercentage / 100)) / tradingEngine.tradingCurrent.strategyOpenStage.stageQuotedAsset.sizeFilled.value)) > tradingEngine.tradingCurrent.position.stopLoss.value ) \n\n{\ntradingEngine.tradingCurrent.position.entryTargetRate.value * (1 + (( tradingEngine.tradingCurrent.tradingEpisode.episodeQuotedAsset.balance.value * (riskPercentage / 100)) / tradingEngine.tradingCurrent.strategyOpenStage.stageQuotedAsset.sizeFilled.value))\n}\n\nelse {\ntradingEngine.tradingCurrent.position.stopLoss.value\n}", + "updated": 1615287799360 + } + ] +} \ No newline at end of file From daf5eb465e7ae25669b2dbaabeda48f9126790e8 Mon Sep 17 00:00:00 2001 From: Smidy13 <77650800+Smidy13@users.noreply.github.com> Date: Wed, 7 Apr 2021 23:34:58 +1200 Subject: [PATCH 03/32] Bug Fix: Getting Started Tutorial Not Loading --- Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js b/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js index b2d119667..7272b7497 100644 --- a/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js +++ b/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js @@ -892,7 +892,6 @@ function newSuperalgosTutorialSpace() { } function playTutorial(node) { - if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return } PAGE_NUMBER = 0 TUTORIAL_NAME = node.name @@ -907,7 +906,6 @@ function newSuperalgosTutorialSpace() { } function resumeTutorial(node) { - if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return } navigationStack = [] node.payload.uiObject.isPlaying = true From 75cb6d54c3250c5aa39dbe90b57c0bb66af38864 Mon Sep 17 00:00:00 2001 From: Brenden Harrell Date: Wed, 7 Apr 2021 07:00:49 -0500 Subject: [PATCH 04/32] title update --- ...up-a-new-chart-001-how-to-set-up-a-new-chart-tutorial.json | 4 ++-- ...-to-set-up-a-new-chart-002-adding-charts-introduction.json | 2 +- ...-set-up-a-new-chart-003-adding-charts-before-we-begin.json | 2 +- ...up-a-new-chart-004-adding-charts-charts-without-tears.json | 4 ++-- ...a-new-chart-005-adding-charts-looking-for-a-quick-fix.json | 2 +- ...t-up-a-new-chart-006-adding-charts-dashing-dashboards.json | 2 +- ...-007-adding-charts-time-machines-hold-it-all-together.json | 4 ++-- ...up-a-new-chart-008-adding-charts-keep-it-in-one-place.json | 4 ++-- ...-up-a-new-chart-009-adding-charts-without-further-ado.json | 2 +- ...-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json | 4 ++-- ...new-chart-011-adding-charts-the-chart-of-many-talents.json | 4 ++-- ...o-set-up-a-new-chart-012-adding-charts-herding-layers.json | 4 ++-- ...-new-chart-013-adding-charts-your-data-treasure-trove.json | 4 ++-- ...-set-up-a-new-chart-014-adding-charts-follow-the-tree.json | 2 +- ...-new-chart-015-adding-charts-the-data-you-want-to-see.json | 4 ++-- ...016-adding-charts-hooking-up-a-chart-to-data-products.json | 2 +- ...7-adding-charts-data-products-make-the-world-go-round.json | 4 ++-- ...-up-a-new-chart-018-adding-charts-make-the-connection.json | 4 ++-- ...o-set-up-a-new-chart-019-adding-charts-add-the-layers.json | 2 +- ...-adding-charts-hooking-up-a-chart-to-a-trading-system.json | 2 +- ...o-set-up-a-new-chart-021-adding-charts-connection-one.json | 4 ++-- ...o-set-up-a-new-chart-022-adding-charts-connection-two.json | 4 ++-- ...-set-up-a-new-chart-023-adding-charts-check-the-chart.json | 2 +- ...to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json | 2 +- ...w-to-set-up-a-new-chart-025-adding-charts-before-i-go.json | 4 ++-- 25 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-001-how-to-set-up-a-new-chart-tutorial.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-001-how-to-set-up-a-new-chart-tutorial.json index 394a62a0e..8f794df31 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-001-how-to-set-up-a-new-chart-tutorial.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-001-how-to-set-up-a-new-chart-tutorial.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "1", - "type": "How to set up a new Chart Tutorial", + "type": "How to Set up a New Chart Tutorial", "definition": { "text": "This Tutorial walks through the basic inner workings of the Charting Space to help you learn how to create your own custom charts.", "updated": 1617371694835 diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json index 6c4d700de..8a673f01a 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "2", "type": "Adding Charts - Introduction", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-003-adding-charts-before-we-begin.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-003-adding-charts-before-we-begin.json index 8038d9aed..afcb1d09b 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-003-adding-charts-before-we-begin.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-003-adding-charts-before-we-begin.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "3", "type": "Adding Charts - Before We Begin", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-004-adding-charts-charts-without-tears.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-004-adding-charts-charts-without-tears.json index ca6b233bd..8efda9073 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-004-adding-charts-charts-without-tears.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-004-adding-charts-charts-without-tears.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "4", - "type": "Adding Charts - Charts without tears", + "type": "Adding Charts - Charts without Tears", "definition": { "text": "I've got your back!", "updated": 1617630234092, diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-005-adding-charts-looking-for-a-quick-fix.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-005-adding-charts-looking-for-a-quick-fix.json index e1cc42a4e..395abc0c4 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-005-adding-charts-looking-for-a-quick-fix.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-005-adding-charts-looking-for-a-quick-fix.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "5", "type": "Adding Charts - Looking for a quick fix?", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json index 265bf920d..821dde1b3 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "6", "type": "Adding Charts - Dashing Dashboards", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json index 59234274f..f22bfcba4 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "7", - "type": "Adding Charts - Time Machines hold it all together", + "type": "Adding Charts - Time Machines Hold It all Together", "definition": { "text": "You've seen these portals to another dimension before! Now let's take a closer look at the magical Time Machine.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-008-adding-charts-keep-it-in-one-place.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-008-adding-charts-keep-it-in-one-place.json index 3636985dd..f849860e9 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-008-adding-charts-keep-it-in-one-place.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-008-adding-charts-keep-it-in-one-place.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "8", - "type": "Adding Charts - Keep it in one place", + "type": "Adding Charts - Keep It in One Place", "definition": { "text": "Setting up a Time Machine will allow you to keep your data synchronized and accessible.", "updated": 1617634554869, diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json index f879347ef..fed53b167 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "9", "type": "Adding Charts - Without Further Ado", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json index 01d0a38a0..c0be6f2fe 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "10", - "type": "Adding Charts - Why is it blank?", + "type": "Adding Charts - Why is It Blank?", "definition": { "text": "Woohoo, you did it! You have added your first custom chart.", "updated": 1617636144825, diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json index ff9ccac8f..7a690ff7f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "11", - "type": "Adding Charts - The Chart of many talents", + "type": "Adding Charts - The Chart of many Talents", "definition": { "text": "The Timeline Chart gives you total control.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json index dc31b5a54..5e8f06418 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "12", - "type": "Adding Charts - Herding layers", + "type": "Adding Charts - Herding Layers", "definition": { "text": "Let's get into the nitty gritty of layer managment.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-013-adding-charts-your-data-treasure-trove.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-013-adding-charts-your-data-treasure-trove.json index 7206684d8..3f2972556 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-013-adding-charts-your-data-treasure-trove.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-013-adding-charts-your-data-treasure-trove.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "13", - "type": "Adding Charts - Your data treasure trove", + "type": "Adding Charts - Your Data Treasure Trove", "definition": { "text": "The Data Storage node holds all the important data your bots work so hard to produce. Think of it like your own personal tresure chest full of data.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json index 92abb3945..52a10725e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "14", "type": "Adding Charts - Follow the Tree!", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json index 6b5d82f7f..888953a13 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "15", - "type": "Adding Charts - The data you want to see", + "type": "Adding Charts - The Data You Want to See", "definition": { "text": "You control the flow of data.", "updated": 1617646900550, diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json index 1beac43e9..235f6a9ae 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "16", "type": "Adding Charts - Hooking up a Chart to Data Products", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json index 06ce7d1c2..7593138bd 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "17", - "type": "Adding Charts - Data Products make the world go round", + "type": "Adding Charts - Data Products Make the World Go Round", "definition": { "text": "We finally found it!", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json index 7b9db2037..821cdcf2f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "18", - "type": "Adding Charts - Make the connection", + "type": "Adding Charts - Make the Connection", "definition": { "text": "Let's make the connection.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json index 3ee4d4a9f..5cc5b184e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "19", "type": "Adding Charts - Add the Layers", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json index 994b70ea3..83d76d334 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "20", "type": "Adding Charts - Hooking up a Chart to a Trading System", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json index 2ab96042b..d1cc1a3fa 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "21", - "type": "Adding Charts - Connection one", + "type": "Adding Charts - Connection One", "definition": { "text": "Let's make the first connection.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json index 815fb62b2..113530d40 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "22", - "type": "Adding Charts - Connection two", + "type": "Adding Charts - Connection Two", "definition": { "text": "And now the second.", "icon": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json index 472f0f855..44df8a9d6 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "23", "type": "Adding Charts - Check the Chart", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json index 5d7bfd085..1d7722279 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json @@ -1,5 +1,5 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "24", "type": "Adding Charts - Easy as 1, 2, 3", "definition": { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-025-adding-charts-before-i-go.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-025-adding-charts-before-i-go.json index a1b180d63..08b004d25 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-025-adding-charts-before-i-go.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-025-adding-charts-before-i-go.json @@ -1,7 +1,7 @@ { - "tutorial": "How to set up a new Chart", + "tutorial": "How to Set up a New Chart", "pageNumber": "25", - "type": "Adding Charts - Before I go", + "type": "Adding Charts - Before I Go", "definition": { "text": "Want some more help figuring out complex chart configurations? You are in luck! I have some friends who would love to help you out.", "icon": { From 1144e5ee4ac60db6f41501e5bd34e9d1763e1be2 Mon Sep 17 00:00:00 2001 From: Brenden Harrell Date: Wed, 7 Apr 2021 22:12:39 -0500 Subject: [PATCH 05/32] Revisions to Charting Space Tutorial pt 1 --- ...-chart-002-adding-charts-introduction.json | 9 ++--- ...-006-adding-charts-dashing-dashboards.json | 17 +++++----- ...ts-time-machines-hold-it-all-together.json | 4 +-- ...009-adding-charts-without-further-ado.json | 17 +++++++--- ...art-010-adding-charts-why-is-it-blank.json | 8 +++-- ...ding-charts-the-chart-of-many-talents.json | 9 ++--- ...hart-012-adding-charts-herding-layers.json | 8 ++--- ...art-014-adding-charts-follow-the-tree.json | 25 +++++++++----- ...dding-charts-the-data-you-want-to-see.json | 9 ++--- ...s-hooking-up-a-chart-to-data-products.json | 19 +++++++---- ...data-products-make-the-world-go-round.json | 25 -------------- ...018-adding-charts-make-the-connection.json | 8 +++-- ...hart-019-adding-charts-add-the-layers.json | 13 +++----- ...dding-charts-dashboards-in-the-future.json | 25 ++++++++++++++ ....5-adding-charts-add-a-timeline-chart.json | 33 +++++++++++++++++++ 15 files changed, 137 insertions(+), 92 deletions(-) delete mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-6.5-adding-charts-dashboards-in-the-future.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-add-a-timeline-chart.json diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json index 8a673f01a..fd97991c8 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-002-adding-charts-introduction.json @@ -13,13 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "The charting system within Superalgos is quite powerful! It pulls together information from across the entire system so that you can conveniently visualize it in one place.", - "updated": 1617369523502 - }, - { - "style": "Text", - "text": "As I am sure you have figured out by now, there are a lot of moving pieces within Superalgos. The Charting Space lets you tap into the specific information you want to see. You can look at different combinations of Indicators, Backtesting and Live Trading results, even data from different Markets and Exchanges! This flexibility makes it possible to customize charts to your heart’s content. Pretty cool right!", - "updated": 1617631456321 + "text": "The charting system within Superalgos is quite powerful! It pulls together information from across the entire system so that you can conveniently visualize it in one place. As I am sure you have figured out by now, there are a lot of moving pieces within Superalgos. The Charting Space lets you tap into the specific information you want to see. You can look at different combinations of Indicators, Backtesting and Live Trading results, even data from different Markets and Exchanges! This flexibility makes it possible to customize charts to your heart’s content. Pretty cool right!", + "updated": 1617796990054 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json index 821dde1b3..54853e277 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-006-adding-charts-dashing-dashboards.json @@ -13,17 +13,18 @@ "paragraphs": [ { "style": "Text", - "text": "To get us started, I want you to get a little more comfortable with how the Charting Space is set up. Expand the Charting Space node and take a look at the Dashboards underneath. What do you notice?", - "updated": 1617326642397 + "text": "To get us started, I want you to get a little more comfortable with how the Charting Space is set up.", + "updated": 1617798279418 + }, + { + "style": "Callout", + "text": "Expand the Charting Space node and take a look at the Dashboards underneath. What do you notice? ", + "updated": 1617798044669 }, { "style": "Text", - "text": "That’s right! There is one Dashboard set up for Backtesting and one set up for Live Trading. Dashboards are a convenient way to group charts according to type. ", - "updated": 1617635396701 - }, - { - "style": "Note", - "text": "Eventually Dashboards will be used to bring multiple Time Machines together in useful configurations, but for right now they helps us stay organized." + "text": "That’s right! There is one Dashboard set up for Backtesting and one set up for Live Trading. Dashboards are a convenient way to group charts according to type.", + "updated": 1617798035878 }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json index f22bfcba4..b44e1668f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-007-adding-charts-time-machines-hold-it-all-together.json @@ -13,8 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "As you can see, each dashboard has a Time Machine attached to it. You have already encountered time machines in previous tutorials. But today we are going to be working with them a lot more closely. Take a minute and read their documentation page to get a better idea of what they do.", - "updated": 1617327414064 + "text": "You might have noticed each dashboard has a Time Machine attached to it. You have already encountered time machines in previous tutorials. But today we are going to be working with them a lot more closely. Take a minute and read their documentation page to get a better idea of what they do.", + "updated": 1617799568096 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json index fed53b167..c2b3abada 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-009-adding-charts-without-further-ado.json @@ -13,13 +13,22 @@ "paragraphs": [ { "style": "Text", - "text": "Enough chit-chat, let’s start adding some charts! Hover over the Testing Environment Dashboard and click Add Time Machine. Then add a name that makes it easy to identify.", - "updated": 1617635008264 + "text": "Enough chit-chat, let’s start adding some charts! ", + "updated": 1617799641215 + }, + { + "style": "Callout", + "text": "Hover over the Testing Environment Dashboard and click Add Time Machine. ", + "updated": 1617799706852 }, { "style": "Text", - "text": "Now that we have something to hold our charts, let's go ahead and add one. Hover over your time machine and click Add Timeline Chart (make sure to name it as well).", - "updated": 1617635775344 + "text": "Make sure to name it something you will recognize. A good naming practice is to reference the Trading System and type of Trading Session that will be connected to the chart. For us that would be: ", + "updated": 1617800245292 + }, + { + "style": "Json", + "text": "Lightning Strike Backtesting Session" }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json index c0be6f2fe..2921f3e0c 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-010-adding-charts-why-is-it-blank.json @@ -17,12 +17,14 @@ "updated": 1617636174999 }, { - "style": "Text", - "text": " If you check the Charting Space, your Time Machine is there, but it is totally blank. That’s because we haven’t hooked it up to any of your data." + "style": "Callout", + "text": "Check the Charting Space. Your Time Machine is there, but it is totally blank. ", + "updated": 1617801603388 }, { "style": "Text", - "text": "Let’s change that!" + "text": "That’s because we haven’t hooked it up to any of your data. Let’s change that!", + "updated": 1617801613196 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json index 7a690ff7f..e4828a6d6 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-011-adding-charts-the-chart-of-many-talents.json @@ -13,13 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "As I mentioned earlier, one of the main features the Charting Space offers is the ability to combine many different types of data all in one place. ", - "updated": 1617636673390 - }, - { - "style": "Text", - "text": "The Timeline Chart gives you this control! Each timeline chart allows you to collect the data you wish to see under a Layer Manager. As you may remember, the layer manager is what allows you to turn different layers on and off while inside a Time Machine.", - "updated": 1617661192637 + "text": "As I mentioned earlier, one of the main features the Charting Space offers is the ability to combine many different types of data all in one place. The Timeline Chart gives you this control! Each timeline chart allows you to collect the data you wish to see under a Layer Manager. As you may remember, the layer manager is what allows you to turn different layers on and off while inside a Time Machine.", + "updated": 1617839354763 }, { "style": "Important", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json index 5e8f06418..eb81507c5 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-012-adding-charts-herding-layers.json @@ -13,12 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "Layer Managers keep track of all the layers connected beneath them. They are also the nodes that accept references to a variety of Data Mine Products. By establishing references with a particular mine we can easily add all the data associated with it. ", - "updated": 1617640517891 - }, - { - "style": "Text", - "text": "The three main types of data are:" + "text": "Layer Managers keep track of all the layers connected beneath them. They are also the nodes that accept references to a variety of Data Mine Products. By establishing references with a particular Mine, we can easily add all the data associated with it. The three main types of data are:", + "updated": 1617839461481 }, { "style": "List", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json index 52a10725e..8f8b605e8 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-014-adding-charts-follow-the-tree.json @@ -3,23 +3,32 @@ "pageNumber": "14", "type": "Adding Charts - Follow the Tree!", "definition": { - "text": "Follow the Data Storage hierarchy and find the Data Mine Products.", + "text": "Follow the Data Mines Data hierarchy and find the Data Mine Products.", "icon": { "name": "data-mines-data", "project": "Superalgos" }, - "updated": 1617328950687 + "updated": 1617849486659 }, "paragraphs": [ { - "style": "Text", - "text": "To do this, pin and drag your whole Time Machine over to the Network node and find the Data Storage node. Expand the Data Storage node. You should notice that there are three branches. One for each type of data we can access in our charts. Since we are interested in Data Mine Products, expand the Data Mines Data node and follow it down. Do you notice any similarity with the other parts of Superalgos you’ve seen? That’s right! The hierarchy is organized according to Project, Exchange, Market, and Data Mine.", - "updated": 1617452392093 + "style": "Callout", + "text": "Keep following the hierarchy. See if you can find the Data Mine Products nodes on your own.", + "updated": 1617849736915 }, { - "style": "Note", - "text": "This is the same basic organization you will find with other types of data as well.", - "updated": 1617328905528 + "style": "Text", + "text": "Did you find them? Keep going farther down the hierarchy until you see them!", + "updated": 1617849595158 + }, + { + "style": "Text", + "text": "" + }, + { + "style": "Important", + "text": "You should see three data mine products nodes. One for each Data Mine install within this Workspace.", + "updated": 1617849622065 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json index 888953a13..1ba1a6240 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-015-adding-charts-the-data-you-want-to-see.json @@ -13,12 +13,13 @@ "paragraphs": [ { "style": "Text", - "text": "The granularity of the Data Storage hierarchy means that you can access Data Products in any combination. Do you want to see data from two different exchanges on the same market? Easily possible. Do you want to see data from two similar markets side by side? Piece of cake! The combinations of data you can view within your charts is truly up to your imagination. ", - "updated": 1617646868051 + "text": "Do you notice any similarity with the other parts of Superalgos you’ve seen? That’s right! The hierarchy is organized according to Project, Exchange, Market, and Data Mine. This is the same basic organization you will find with all data here in Superalgos.", + "updated": 1617840932423 }, { - "style": "Text", - "text": "Whew! I am getting a little carried away. My friends will cover these exciting possiblities in a little while. Let's refocus and finish adding those Data Mine Products." + "style": "Important", + "text": "This granularity means you can access Data Products in any combination. Do you want to see data from two different exchanges on the same market? Easily possible. Do you want to see data from two similar markets side by side? Piece of cake! The combinations of data you can view within your charts is truly up to your imagination.", + "updated": 1617842448486 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json index 235f6a9ae..68ea99c43 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-016-adding-charts-hooking-up-a-chart-to-data-products.json @@ -3,23 +3,28 @@ "pageNumber": "16", "type": "Adding Charts - Hooking up a Chart to Data Products", "definition": { - "text": "We are almost to the node we need!", + "text": "Get your Time Machine in position. ", "icon": { "name": "data-mine-products", "project": "Superalgos" }, - "updated": 1617329505743 + "updated": 1617841161571 }, "paragraphs": [ { "style": "Text", - "text": "We've been working on adding some Data Mine Products to our chart. Let's be a little more specific, we are going to add the data mine products for the Masters Data Mine in the Binance BTC/USDT market. As you follow the hierarchy down you should see the Market Data Products nodes for the Binance BTC/USDT market.", - "updated": 1617452481209 + "text": "Whew! I am getting a little carried away. My friends will cover these exciting possiblities in a little while. Let's refocus and finish adding those Data Mine Products we've been working on.", + "updated": 1617841292233 }, { - "style": "Note", - "text": "There are three data mines installed in this Workspace. You will see one Market Data Products node for each market.", - "updated": 1617647424199 + "style": "Callout", + "text": "Pin and drag your whole Time Machine over to Data Mine Products nodes you found earlier.", + "updated": 1617842351106 + }, + { + "style": "Success", + "text": "Don't forget Ctrl + ← → ↑ ↓. It's a bit of a trek!", + "updated": 1617841738597 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json deleted file mode 100644 index 7593138bd..000000000 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-017-adding-charts-data-products-make-the-world-go-round.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tutorial": "How to Set up a New Chart", - "pageNumber": "17", - "type": "Adding Charts - Data Products Make the World Go Round", - "definition": { - "text": "We finally found it!", - "icon": { - "name": "data-mine-products", - "project": "Superalgos" - }, - "updated": 1617330357641 - }, - "paragraphs": [ - { - "style": "Text", - "text": "Underneath the Market Data Products node are the nodes we are after, the Data Mine Products nodes. These nodes are the ones we will connect to our chart! If the Data Storage node was your treasure chest, Data Products are your gold!", - "updated": 1617452590612 - }, - { - "style": "Note", - "text": "You should see one Data Mine Products node for each data mine you have installed in your workspace. I hope the pattern is starting to sink in for you!", - "updated": 1617329732074 - } - ] -} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json index 821cdcf2f..281d7358b 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-018-adding-charts-make-the-connection.json @@ -13,8 +13,12 @@ "paragraphs": [ { "style": "Text", - "text": "Find the Layer Manager under the Timeline Chart you added earlier. Then establish a reference between it and the Masters Data Mine Products node. ", - "updated": 1617648263797 + "text": "Out of the three Data Mine Products nodes available, we are going to connect our chart to the Masters Data Mine.", + "updated": 1617850389465 + }, + { + "style": "Callout", + "text": "Find the Layer Manager under the Timeline Chart you added earlier. Then establish a reference between it and the Masters Data Mine Products node." }, { "style": "Success", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json index 5cc5b184e..20f294e9e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-019-adding-charts-add-the-layers.json @@ -12,18 +12,13 @@ }, "paragraphs": [ { - "style": "Text", - "text": "The last step is to hover over the Layer Manager and click Add All Mine Layers. This will automatically add references to all of the individual layers produced by the Data Mine. ", - "updated": 1617656376504 - }, - { - "style": "Important", - "text": "Make sure to run all Data Tasks and wait for them to reach 100%.", - "updated": 1617656439904 + "style": "Callout", + "text": "The last step is to hover over the Layer Manager and click Add All Mine Layers. ", + "updated": 1617850457047 }, { "style": "Text", - "text": "Now you should be able to check the Charting Space and see the indicators from the Data Mine showing up in your chart!" + "text": "This will automatically add references to all of the individual layers produced by the Data Mine." }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-6.5-adding-charts-dashboards-in-the-future.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-6.5-adding-charts-dashboards-in-the-future.json new file mode 100644 index 000000000..4820791a2 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-6.5-adding-charts-dashboards-in-the-future.json @@ -0,0 +1,25 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "6.5", + "type": "Adding Charts - Dashboards in the Future", + "definition": { + "text": "The future holds more in store.", + "updated": 1617798674297, + "icon": { + "name": "under-construction", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Text", + "text": "Eventually Dashboards will be used to bring multiple Time Machines together in useful configurations, but for right now they helps us stay organized.", + "updated": 1617798575876 + }, + { + "style": "Important", + "text": "Superalgos is a community project. If you are a developer that would like to see this feature come to life, you can help make it happen!", + "updated": 1617799444931 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-add-a-timeline-chart.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-add-a-timeline-chart.json new file mode 100644 index 000000000..faeaf8cf7 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-add-a-timeline-chart.json @@ -0,0 +1,33 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "9.5", + "type": "Adding Charts - Add a Timeline Chart", + "definition": { + "text": "Now that we have something to hold our charts, let's go ahead and add one!", + "updated": 1617800759702, + "icon": { + "name": "timeline-chart", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Callout", + "text": "Hover over your Time Machine and click Add Timeline Chart.", + "updated": 1617800816707 + }, + { + "style": "Text", + "text": "Just like with time machines, giving a helpful name to a Timeline Chart is important. A good naming practice is to name timeline charts after the Data Mine or Data Product with which it will be connected. Today we will be adding Data Mine data to this timeline chart. So a helpful name would be:", + "updated": 1617801165071 + }, + { + "style": "Json", + "text": "Data Mine Layers" + }, + { + "style": "Text", + "text": "" + } + ] +} \ No newline at end of file From d3f514e66aa26dae341c19a7ac07e4bfd8bb8d49 Mon Sep 17 00:00:00 2001 From: Brenden Harrell Date: Thu, 8 Apr 2021 08:34:49 -0500 Subject: [PATCH 06/32] Revised Charting Space Tutorial pt2 --- ...ooking-up-a-chart-to-a-trading-system.json | 14 ++------- ...hart-021-adding-charts-connection-one.json | 19 ++++++++---- ...hart-022-adding-charts-connection-two.json | 19 ++++++++---- ...art-023-adding-charts-check-the-chart.json | 14 ++++----- ...chart-024-adding-charts-easy-as-1-2-3.json | 14 ++------- ....5-adding-charts-back-to-data-storage.json | 30 +++++++++++++++++++ ...-adding-charts-another-timeline-chart.json | 28 +++++++++++++++++ ...adding-charts-don’t-forget-the-layers.json | 24 +++++++++++++++ ...arts-–-don’t-forget-to-add-the-layers.json | 24 +++++++++++++++ ...3.5-adding-charts-not-seeing-anything.json | 29 ++++++++++++++++++ ...ew-chart-9.5-adding-charts-it’s-alive.json | 30 +++++++++++++++++++ 11 files changed, 201 insertions(+), 44 deletions(-) create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.5-adding-charts-back-to-data-storage.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.7-adding-charts-another-timeline-chart.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-don’t-forget-the-layers.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-–-don’t-forget-to-add-the-layers.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-3.5-adding-charts-not-seeing-anything.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-it’s-alive.json diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json index 83d76d334..585d08402 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-020-adding-charts-hooking-up-a-chart-to-a-trading-system.json @@ -13,18 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "The next thing you will want to connect with most charts are the results of your trading strategies. For the most part, this is the same as connecting to a Data Mine. There are just a few differences I will walk you through.", - "updated": 1617649096083 - }, - { - "style": "Text", - "text": "One major difference is that each Time Machine can only reference one Trading Session. For example, one Backtesting Session that is associated with one Trading System. This helps keep your charts clean and readable. It would be confusing to see buy orders from two different trading systems all at once!", - "updated": 1617649161505 - }, - { - "style": "Text", - "text": "What this means for connecting a chart is that we need to establish two references in order for things to work.", - "updated": 1617369951260 + "text": "The next thing you will want to connect with most charts are the results of your trading strategies. For the most part, this is the same as connecting to a Data Mine. There are just a few differences I will walk you through. One major difference is that each Time Machine can only reference one Trading Session. For example, one Backtesting Session that is associated with one Trading System. This helps keep your charts clean and readable. It would be confusing to see buy orders from two different trading systems all at once! What this means for connecting a chart is that we need to establish two references in order for things to work.", + "updated": 1617851405458 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json index d1cc1a3fa..62098ca76 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-021-adding-charts-connection-one.json @@ -3,22 +3,31 @@ "pageNumber": "21", "type": "Adding Charts - Connection One", "definition": { - "text": "Let's make the first connection.", + "text": "Let's make the first connection. Go find your Time Machine and drag it back here.", "icon": { "name": "delink-node", "project": "Superalgos" }, - "updated": 1617370061516 + "updated": 1617883855631 }, "paragraphs": [ { "style": "Text", - "text": "The first connection is between a Trading Session and the Time Machine we have been working on. Drag your Time Machine back up to the Network node. Find the Testing Trading Tasks hierarchy. Follow it down until you find the Backtesting Task for the Lightning Strike Trading System. Continue down the hierarchy until you find the Backtesting Session. Now take your Time Machine and create a reference to it.", - "updated": 1617649517982 + "text": "The first connection is between a Trading Session and the Time Machine we have been working on. This reference tells our chart which Trading System and Session to listen for.", + "updated": 1617883945973 + }, + { + "style": "Callout", + "text": "Once you are back create a reference between your Time Machine and the Backtesting Session. " + }, + { + "style": "Text", + "text": "" }, { "style": "Note", - "text": "These steps are the same for connecting to a Live Trading Session. The only difference is following the Production Trading Task hierarchy instead." + "text": "These steps are the same for connecting to a Live Trading Session. The only difference is the Session will be found under the Production Trading Task hierarchy instead.", + "updated": 1617884102564 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json index 113530d40..f7db04a40 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-022-adding-charts-connection-two.json @@ -3,23 +3,30 @@ "pageNumber": "22", "type": "Adding Charts - Connection Two", "definition": { - "text": "And now the second.", + "text": "We are almost there! Go drag your Time Machine back over here.", "icon": { "name": "delink-node", "project": "Superalgos" }, - "updated": 1617374736974 + "updated": 1617886454003 }, "paragraphs": [ { "style": "Text", - "text": "Now we can go back to the Data Storage hierarchy and follow the Trading Mines Data branch until we find the Backtesting Session Reference node that matches the Backtesting Session we just came from.", - "updated": 1617453374362 + "text": "Under the Session Reference node you will see the Trading Mine Products node we are after." + }, + { + "style": "Callout", + "text": "Now create a reference between your new Layer Manager and the Trading Mind Products node.", + "updated": 1617886479339 + }, + { + "style": "Success", + "text": "If you hooked it up correctly, the name Masters should appear over the layer manager." }, { "style": "Text", - "text": "We are almost there! Under the Backtesting Session Reference node you will see a Trading Mine Products node. Just like before, add a new Timeline Chart (don’t forget to name it). Then create a reference between the Trading Mine Products node and the Layer Manager.", - "updated": 1617453393860 + "text": "" } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json index 44df8a9d6..92937b1a7 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-023-adding-charts-check-the-chart.json @@ -11,19 +11,15 @@ } }, "paragraphs": [ - { - "style": "Text", - "text": "Run the Backtesting Session for the Lightning Strike Trading System and wait for it to finish. Then verify things are working in the Charting Space by turning on a few layers.", - "updated": 1617661474803 - }, { "style": "Important", - "text": "Remember to pay attention to the Time Frame and dates the session was run under. Otherwise you won’t see anything!" + "text": "Make sure to run the Backtesting Session for the Lightning Strike Trading System and wait for it to finish.", + "updated": 1617887112622 }, { - "style": "Success", - "text": "The Lightning Strike Backtesting Session was run on the one minute time frame from September 1 2020 to September 2 2020.", - "updated": 1617651027780 + "style": "Callout", + "text": "Check your chart by turning on a few Trading System layers.", + "updated": 1617887153627 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json index 1d7722279..affd1a816 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-024-adding-charts-easy-as-1-2-3.json @@ -13,18 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "Congratulations, your custom chart is now hooked up and working! ", - "updated": 1617370495984 - }, - { - "style": "Text", - "text": "You now know the basic steps of chart creation. You can repeat the same steps, adding more Timeline Charts, to connect any combination of data you want.", - "updated": 1617651306951 - }, - { - "style": "Text", - "text": "Just a quick reminder, the three types of nodes you can connect a Timeline Chart’s Layer Manager to are:", - "updated": 1617370557381 + "text": "Congratulations, your custom chart is now hooked up and working! You now know the basic steps of chart creation. You can repeat the same steps, adding more Timeline Charts, to connect any combination of data you want. Just a quick reminder, the three types of nodes you can connect a Timeline Chart’s Layer Manager to are:", + "updated": 1617886835178 }, { "style": "List", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.5-adding-charts-back-to-data-storage.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.5-adding-charts-back-to-data-storage.json new file mode 100644 index 000000000..66ed9a67b --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.5-adding-charts-back-to-data-storage.json @@ -0,0 +1,30 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "21.5", + "type": "Adding Charts - Back to Data Storage", + "definition": { + "text": "Let's find some more Data Products.", + "updated": 1617883193525, + "icon": { + "name": "trading-mines-data", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Text", + "text": "You should notice there are three branches. One for each type of data we can access in our charts. Since we are now interested in the data from our Trading System, we need the data products held under the Trading Mines Data hierarchy. ", + "updated": 1617884873448 + }, + { + "style": "Callout", + "text": "Just like before, follow the hierarchy until you find the Trading Mine Products nodes.", + "updated": 1617884949563 + }, + { + "style": "Success", + "text": "Make sure to look under the Trading Session Reference nodes!", + "updated": 1617884973014 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.7-adding-charts-another-timeline-chart.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.7-adding-charts-another-timeline-chart.json new file mode 100644 index 000000000..f1e539450 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-1.7-adding-charts-another-timeline-chart.json @@ -0,0 +1,28 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "21.7", + "type": "Adding Charts - Another Timeline Chart", + "definition": { + "text": "To connect with our Trading System we will need another Timeline Chart.", + "updated": 1617885750903, + "icon": { + "name": "timeline-chart", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Callout", + "text": "Go find your Time Machine and add a new Timeline Chart." + }, + { + "style": "Text", + "text": "Remember to name it for easy recognition. If we name it according to type of mine or data. A good name would be:", + "updated": 1617885817072 + }, + { + "style": "Json", + "text": "Trading System Layers" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-don’t-forget-the-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-don’t-forget-the-layers.json new file mode 100644 index 000000000..4aaf2006f --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-don’t-forget-the-layers.json @@ -0,0 +1,24 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "22.5", + "type": "Adding Charts - Don’t Forget the Layers!", + "definition": { + "text": "You’ve done this before!", + "updated": 1617888380713, + "icon": { + "name": "layer", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Callout", + "text": "Hover over the Layer Manager and click Add All Mine Layers. " + }, + { + "style": "Text", + "text": "This is an easy step to forget but very important! If there are't any layers under the layer manager, nothing will show up no matter how hard you try.", + "updated": 1617888419678 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-–-don’t-forget-to-add-the-layers.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-–-don’t-forget-to-add-the-layers.json new file mode 100644 index 000000000..58fc00d90 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-2.5-adding-charts-–-don’t-forget-to-add-the-layers.json @@ -0,0 +1,24 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "22.5", + "type": "Adding Charts – Don’t Forget to Add the Layers!", + "definition": { + "text": "You’ve done this before!", + "updated": 1617888064958, + "icon": { + "name": "layer", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Callout", + "text": "Hover over the Layer Manager and click Add All Mine Layers. " + }, + { + "style": "Text", + "text": "This is an easy step to forget but very important! If there aren't any layers under the layer manager, nothing will show up no matter how hard you try.", + "updated": 1617888163173 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-3.5-adding-charts-not-seeing-anything.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-3.5-adding-charts-not-seeing-anything.json new file mode 100644 index 000000000..a1db51ea3 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-3.5-adding-charts-not-seeing-anything.json @@ -0,0 +1,29 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": " 23.5", + "type": "Adding Charts - Not Seeing Anything?", + "definition": { + "text": "Are you having trouble with the Trading Layers?", + "updated": 1617887420953, + "icon": { + "name": "bot-data-dependencies", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Important", + "text": "Remember to pay attention to the Time Frame and dates the session was run under. Otherwise you won’t see anything!", + "updated": 1617887429273 + }, + { + "style": "Success", + "text": "The Lightning Strike Backtesting Session was run on the one minute time frame from September 1 2020 to September 2 2020.", + "updated": 1617887385163 + }, + { + "style": "Text", + "text": "" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-it’s-alive.json b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-it’s-alive.json new file mode 100644 index 000000000..f865f8ebc --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/how-to-set-up-a-new-chart-9.5-adding-charts-it’s-alive.json @@ -0,0 +1,30 @@ +{ + "tutorial": "How to Set up a New Chart", + "pageNumber": "19.5", + "type": "Adding Charts - It’s Alive!", + "definition": { + "text": "Let's take a look at your new working chart!", + "updated": 1617850745525, + "icon": { + "name": "trading-system", + "project": "Superalgos" + } + }, + "paragraphs": [ + { + "style": "Important", + "text": "First make sure to run all Data Tasks and wait for them to reach 100%.", + "updated": 1617850764129 + }, + { + "style": "Callout", + "text": "Fire up the Charting Space and take a look at your Chart. Have some fun and turn a few layers on and off.", + "updated": 1617850952279 + }, + { + "style": "Text", + "text": "If can see layers showing up when you turn them on, great job! If nothing is showing up, go back over previous steps and make sure you didn't miss anything.", + "updated": 1617851145572 + } + ] +} \ No newline at end of file From c9e26f5396b44837ef109869002f4ea3872b217b Mon Sep 17 00:00:00 2001 From: Brenden Harrell Date: Thu, 8 Apr 2021 08:40:21 -0500 Subject: [PATCH 07/32] Updated Workspace Creating Custom Charts --- .../Superalgos/Plugins/Workspaces/Creating-Custom-Charts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Projects/Superalgos/Plugins/Workspaces/Creating-Custom-Charts.json b/Projects/Superalgos/Plugins/Workspaces/Creating-Custom-Charts.json index 93f1de96a..873292da9 100644 --- a/Projects/Superalgos/Plugins/Workspaces/Creating-Custom-Charts.json +++ b/Projects/Superalgos/Plugins/Workspaces/Creating-Custom-Charts.json @@ -1 +1 @@ -{"type":"Workspace","name":"Creating Custom Charts","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataTasks":{"type":"Data Tasks","name":"New Data Tasks","project":"Superalgos","projectDataTasks":[{"type":"Project Data Tasks","name":"Superalgos","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binanceus","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"d244c564-4e86-43c7-9796-dc3b6294ec8b","savedPayload":{"position":{"x":26497.378634092645,"y":28190.39686701245},"targetPosition":{"x":26757.186255227978,"y":28040.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"343313ae-5705-484d-8bf8-aed25ba61cfa","savedPayload":{"position":{"x":26757.186255227978,"y":28040.39686701245},"targetPosition":{"x":27016.99387636331,"y":27890.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"a8f38508-1cac-4ab1-815f-d338fc813377","savedPayload":{"position":{"x":27016.99387636331,"y":27890.39686701245},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"f0ef12ed-f0fd-4b88-8e15-27cf24265a5f","savedPayload":{"position":{"x":26407.46825383848,"y":27662.75115348169},"targetPosition":{"x":26697.2460017252,"y":27585.105439950934},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7c8b312c-09bf-4c59-853f-1592391a9c57","savedPayload":{"position":{"x":26485.113967369238,"y":27372.97340559497},"targetPosition":{"x":26697.2460017252,"y":27585.105439950934},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"8d58e84b-d7ef-464f-8079-0ec0887e3da3","savedPayload":{"position":{"x":26697.2460017252,"y":27585.105439950934},"targetPosition":{"x":26987.023749611923,"y":27662.75115348169},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bf29e3bd-9386-408b-9091-042da0c53e81","savedPayload":{"position":{"x":26987.023749611923,"y":27662.75115348169},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Market","project":"Superalgos","id":"a707814e-b81b-4102-9b5b-4e2fe969324f","savedPayload":{"position":{"x":26716.99387636331,"y":27070.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"5d9b2729-43fb-4e7e-aa4f-b8477c424e51"}}},{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Daily","project":"Superalgos","id":"c5395fbe-4b5a-4492-a7fb-e2d259905e27","savedPayload":{"position":{"x":26976.801497498644,"y":26920.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"be19d91b-9337-4f84-96b3-f4e54ea12df5"}}}],"id":"112be2cf-74ea-4272-9566-cf0cd24c111c","savedPayload":{"position":{"x":26976.801497498644,"y":27220.781624741783},"targetPosition":{"x":27126.801497498644,"y":27480.589245877116},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e74c3232-7b59-4006-87fa-b3b2a328a52b","savedPayload":{"position":{"x":27126.801497498644,"y":27480.589245877116},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c193ecbb-c3e0-4fd5-94ed-bb6356d1d5ea","savedPayload":{"position":{"x":27276.801497498644,"y":27740.39686701245},"targetPosition":{"x":27566.579245385365,"y":27818.042580543206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"85224e5e-f3ee-4e8d-b9bd-e5901bd49b33","savedPayload":{"position":{"x":27566.579245385365,"y":27818.042580543206},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Tasks","name":"Sparta","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Sparta","project":"Superalgos","tasks":[{"type":"Task","name":"Simple Moving Average (SMA)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Simple Moving Average (SMA)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Simple Moving Average (SMA) Multi-Period-Market","project":"Superalgos","id":"577e56c5-4bae-4528-8ed4-f7032a6cc2b2","savedPayload":{"position":{"x":26676.801497498644,"y":27220.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"456269f6-9849-4d5f-9c8c-7cd7d1eef297"}}},{"type":"Indicator Process Instance","name":"Simple Moving Average (SMA) Multi-Period-Daily","project":"Superalgos","id":"1ebcdf4e-828a-4fc6-8516-1fd1466f747f","savedPayload":{"position":{"x":26716.99387636331,"y":27070.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"333ae5d7-7ec1-4f08-b206-91e3b4f2c99f"}}}],"id":"78619a39-67e7-4be3-92d4-794e699bc134","savedPayload":{"position":{"x":26976.801497498644,"y":27220.781624741783},"targetPosition":{"x":27266.579245385365,"y":27298.42733827254},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c1c85b8e-3c0c-4527-b4c3-b8a9f2bfc22b","savedPayload":{"position":{"x":27266.579245385365,"y":27298.42733827254},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Moving Average Convergence Diveregence (MACD) Multi-Period-Market","project":"Superalgos","id":"f22238fe-0c4c-44bb-9a21-edc1b6ff4eb8","savedPayload":{"position":{"x":27044.224958916122,"y":26644.32577517667},"targetPosition":{"x":27256.356993272086,"y":26856.457809532632},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"44019efe-950a-4eec-a546-cd2ee26818b9"}}},{"type":"Indicator Process Instance","name":"Moving Average Convergence Diveregence (MACD) Multi-Period-Daily","project":"Superalgos","id":"9cc5b202-a9c4-4632-9c21-3b01a2f74255","savedPayload":{"position":{"x":27178.71127974133,"y":26566.68006164591},"targetPosition":{"x":27256.356993272086,"y":26856.457809532632},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"8e5db945-8507-4489-9288-21cfa1e9301c"}}}],"id":"4efb5b27-ab99-4e9a-a2a3-8990e8713fe2","savedPayload":{"position":{"x":27256.356993272086,"y":26856.457809532632},"targetPosition":{"x":27406.356993272086,"y":27116.265430667965},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"129e39d0-f14f-449f-96ba-b7c2f40ba33a","savedPayload":{"position":{"x":27406.356993272086,"y":27116.265430667965},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Relative Strenght Index (RSI)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Relative Strenght Index (RSI)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Relative Strenght Index (RSI) Multi-Period-Market","project":"Superalgos","id":"824c6e6f-65af-464b-948b-d529f5776982","savedPayload":{"position":{"x":27711.6484203336,"y":26496.517556029856},"targetPosition":{"x":27711.6484203336,"y":26796.517556029856},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"96f31416-5090-428a-be83-985a0b3ab275"}}},{"type":"Indicator Process Instance","name":"Relative Strenght Index (RSI) Multi-Period-Daily","project":"Superalgos","id":"ced7678d-e4c1-4891-be78-265d79aab04c","savedPayload":{"position":{"x":27861.6484203336,"y":26536.709934894523},"targetPosition":{"x":27711.6484203336,"y":26796.517556029856},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"f1177bcd-22dc-425b-8f30-878844aa82b8"}}}],"id":"1cacb36f-7b2a-499c-aeb0-a6b0a4a1969a","savedPayload":{"position":{"x":27711.6484203336,"y":26796.517556029856},"targetPosition":{"x":27634.002706802843,"y":27086.295303916577},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bbdf0a91-954a-422d-bff1-b4c206425006","savedPayload":{"position":{"x":27634.002706802843,"y":27086.295303916577},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"172d0669-960d-47c7-aba9-8984b98389ac","savedPayload":{"position":{"x":27556.356993272086,"y":27376.073051803298},"targetPosition":{"x":27706.356993272086,"y":27635.88067293863},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b9dc8332-3efb-46a4-9e39-7fd204ac0173","savedPayload":{"position":{"x":27706.356993272086,"y":27635.88067293863},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Tasks","name":"Alpha","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Alpha","project":"Superalgos","tasks":[{"type":"Task","name":"Stochastic","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Stochastic","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Stochastic Multi-Period-Market","project":"Superalgos","id":"244f2d9d-0b4d-4a73-acac-b95c7f060c20","savedPayload":{"position":{"x":28166.939847395115,"y":26436.57730252708},"targetPosition":{"x":28166.939847395115,"y":26736.57730252708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"6a6a6533-21a9-4be9-b2f0-ace1adfe45b8"}}},{"type":"Indicator Process Instance","name":"Stochastic Multi-Period-Daily","project":"Superalgos","id":"93f3e4f4-1774-481a-be53-20c0c19fb54f","savedPayload":{"position":{"x":28316.939847395115,"y":26476.769681391746},"targetPosition":{"x":28166.939847395115,"y":26736.57730252708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"6a39c43d-0ad2-4c98-ae06-6e40f55d1753"}}}],"id":"8e66e327-a785-489b-ab0b-f3bc84546d1e","savedPayload":{"position":{"x":28166.939847395115,"y":26736.57730252708},"targetPosition":{"x":28089.294133864358,"y":27026.3550504138},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"66046624-d8cc-4d5b-a24a-4ce998353616","savedPayload":{"position":{"x":28089.294133864358,"y":27026.3550504138},"targetPosition":{"x":28011.6484203336,"y":27316.13279830052},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e66a0d4c-201f-4955-83d4-9e0a5308ad80","savedPayload":{"position":{"x":28011.6484203336,"y":27316.13279830052},"targetPosition":{"x":27934.002706802843,"y":27605.910546187242},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f4378a66-6833-4164-bec1-4f1c3b42d5b4","savedPayload":{"position":{"x":27934.002706802843,"y":27605.910546187242},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Alpha","id":"511bef1e-62d8-4ff9-8d87-15bd0d3d630c"}}}],"id":"70d459d6-d270-49e0-b70d-2053c65a40e2","savedPayload":{"position":{"x":27856.356993272086,"y":27895.688294073963},"targetPosition":{"x":28006.356993272086,"y":28155.495915209296},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"af949a76-a6f4-4ec6-869e-f240480eea81","savedPayload":{"position":{"x":28006.356993272086,"y":28155.495915209296},"targetPosition":{"x":28156.356993272086,"y":28415.30353634463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"9b93b56d-dccf-4a8c-bbd0-8c608c31363c","savedPayload":{"position":{"x":28156.356993272086,"y":28415.30353634463},"targetPosition":{"x":28306.356993272086,"y":28675.11115747996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"40af91d9-431c-4b7d-addc-aed37bc2f3fe","savedPayload":{"position":{"x":28306.356993272086,"y":28675.11115747996},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"learningTasks":{"type":"Learning Tasks","name":"New Learning Tasks","project":"Superalgos","projectLearningTasks":[{"type":"Project Learning Tasks","name":"Superalgos","project":"Superalgos","exchangeLearningTasks":[],"id":"ddd4bf4d-46fd-4c16-86d3-1785f5ad629e","savedPayload":{"position":{"x":25559.356993272086,"y":30511.30353634463},"targetPosition":{"x":25409.356993272086,"y":30771.11115747996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"0818dfbe-61ea-40b8-8544-bee25d7f45be","savedPayload":{"position":{"x":28606.356993272086,"y":28675.11115747996},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"testingTradingTasks":{"type":"Testing Trading Tasks","name":"New Testing Trading Tasks","project":"Superalgos","projectTradingTasks":[{"type":"Project Trading Tasks","name":"Superalgos","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binanceus","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","tradingMineTasks":[{"type":"Trading Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Lightning Strike","project":"Superalgos","bot":{"type":"Trading Bot Instance","name":"Low Frequency","config":"{}","project":"Superalgos","processes":[{"type":"Trading Process Instance","name":"Low Frequency Trading","project":"Superalgos","session":{"type":"Backtesting Session","name":"Lightning Strike","config":"{\"folderName\":\"Lightning-Strike\"}","project":"Superalgos","tradingParameters":{"type":"Trading Parameters","name":"New Parameters","project":"Superalgos","sessionBaseAsset":{"type":"Session Base Asset","name":"","config":"{\n\"initialBalance\": 0,\n\"minimumBalance\": 0\n}","project":"Superalgos","id":"fb252bd6-3e7d-49a0-9fc6-be392be5db5b","savedPayload":{"position":{"x":31532.291877706186,"y":28455.48478700282},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"sessionQuotedAsset":{"type":"Session Quoted Asset","name":"","config":"{\n\"initialBalance\": 1000\n}","project":"Superalgos","id":"ed578090-732c-4e41-a4ae-9d4f34607170","savedPayload":{"position":{"x":31621.55868811598,"y":28426.48024208079},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeRange":{"type":"Time Range","name":"New Time Range","config":"{ \n\"initialDatetime\": \"2020-09-01\",\n\"finalDatetime\": \"2020-09-02\",\n \"allowStartingFromThePast\": false\n}","project":"Superalgos","id":"47fa4509-16f4-42b7-9453-fa3b3d2885b0","savedPayload":{"position":{"x":31715.41936714012,"y":28426.48024208079},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrame":{"type":"Time Frame","name":"New Time Frame","config":"{ \n\"label\": \"01-min\"\n}","project":"Superalgos","id":"dfe3514c-1aa9-4cea-bb2d-e6657037e69d","savedPayload":{"position":{"x":31804.686177549913,"y":28455.48478700282},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"slippage":{"type":"Slippage","name":"New Slippage","config":"{ \n\"marketOrderRate\": 0.1,\n\"stopLoss\": 0.2,\n\"takeProfit\": 0.3\n}","project":"Superalgos","id":"c711e510-373f-468d-8ed9-1601da6a06f5","savedPayload":{"position":{"x":31880.621061984013,"y":28510.654709903367},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"feeStructure":{"type":"Fee Structure","name":"New Fee Structure","config":"{ \n\"maker\": 0.1,\n\"taker\": 0.1\n}","project":"Superalgos","id":"fdc7c383-8301-4393-b415-8c2d542e05fe","savedPayload":{"position":{"x":31935.79098488456,"y":28586.589594337467},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"snapshots":{"type":"Snapshots","name":"New Snapshots","config":"{ \n\"strategy\": true,\n\"position\": true\n}","project":"Superalgos","id":"28db17c9-2703-430b-a162-5e04b68640a3","savedPayload":{"position":{"x":31964.79552980659,"y":28675.85640474726},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"heartbeats":{"type":"Heartbeats","name":"New Heartbeats","config":"{ \n\"date\": true,\n\"candleIndex\": false\n}","project":"Superalgos","id":"78270062-7d10-4afa-baee-2bda8a4b4ed2","savedPayload":{"position":{"x":31964.79552980659,"y":28769.7170837714},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"userDefinedParameters":{"type":"User Defined Parameters","name":"New User Defined Parameters","config":"{ \n\"param1Name\": \"A text string value example\",\n\"param2Name\": 0\n}","project":"Superalgos","id":"4c9cdc50-70c0-43ee-ad54-052f8b7ecbc8","savedPayload":{"position":{"x":31935.79098488456,"y":28858.983894181194},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e79ab7df-ba40-46aa-abcd-63df8031a931","savedPayload":{"position":{"x":31668.48902762805,"y":28722.78674425933},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingSystemReference":{"type":"Trading System Reference","name":"Lightning Strike","project":"Superalgos","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2","savedPayload":{"position":{"x":31756.356993272086,"y":28934.918778615294},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},"tradingEngineReference":{"type":"Trading Engine Reference","name":"Low-Frequency","project":"Superalgos","id":"720feaab-efc8-435a-bb3c-ab4e33ed1ca2","savedPayload":{"position":{"x":31668.48902762805,"y":29147.050812971258},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading Engine","name":"Low-Frequency","id":"eb20f622-71bf-4479-a574-d2320e1d4bd1"}}},"id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f","savedPayload":{"position":{"x":31456.356993272086,"y":28934.918778615294},"targetPosition":{"x":31156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"60a5e5c0-cfb3-4488-b46c-55d637212aa5","savedPayload":{"position":{"x":31156.356993272086,"y":28934.918778615294},"targetPosition":{"x":30856.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Trading","id":"a8c8d761-96e5-4a86-9285-6c3881d61442"}}}],"id":"cbfbb9e7-9c30-4482-8a9f-4c90771feffc","savedPayload":{"position":{"x":30856.356993272086,"y":28934.918778615294},"targetPosition":{"x":30556.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"08222935-2499-4a3e-a927-4f5dfbc392df","savedPayload":{"position":{"x":30556.356993272086,"y":28934.918778615294},"targetPosition":{"x":30256.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"56c5656b-a7e0-42ed-92d6-631e78ca99d0","savedPayload":{"position":{"x":30256.356993272086,"y":28934.918778615294},"targetPosition":{"x":29956.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1ce02342-473e-4614-ac76-c7788f56ab8e","savedPayload":{"position":{"x":29956.356993272086,"y":28934.918778615294},"targetPosition":{"x":29656.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"2db856e0-4719-408c-88bc-5b47d412c066","savedPayload":{"position":{"x":29656.356993272086,"y":28934.918778615294},"targetPosition":{"x":29356.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"ba36975c-08d6-458d-b7c0-eb4684a85b5d","savedPayload":{"position":{"x":29356.356993272086,"y":28934.918778615294},"targetPosition":{"x":29056.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"55c01047-3fce-41b3-9214-2e885f28b987","savedPayload":{"position":{"x":29056.356993272086,"y":28934.918778615294},"targetPosition":{"x":28756.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"8117db0a-e418-4f56-8fe4-fda2ddac1cbb","savedPayload":{"position":{"x":28756.356993272086,"y":28934.918778615294},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"productionTradingTasks":{"type":"Production Trading Tasks","name":"New Production Trading Tasks","project":"Superalgos","projectTradingTasks":[{"type":"Project Trading Tasks","name":"Superalgos","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binanceus","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","tradingMineTasks":[{"type":"Trading Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Lightning Strike","project":"Superalgos","bot":{"type":"Trading Bot Instance","name":"Low Frequency","config":"{}","project":"Superalgos","processes":[{"type":"Trading Process Instance","name":"Low Frequency Trading","project":"Superalgos","session":{"type":"Live Trading Session","name":"Lightning Strike","config":"{\"folderName\":\"Lightning-Strike\"}","project":"Superalgos","tradingParameters":{"type":"Trading Parameters","name":"New Parameters","project":"Superalgos","sessionBaseAsset":{"type":"Session Base Asset","name":"","config":"{\n\"initialBalance\": 0,\n\"minimumBalance\": 0\n}","project":"Superalgos","id":"5db563b5-a8d6-48c6-a34e-bbca8825ce37","savedPayload":{"position":{"x":27214.318791376507,"y":32665.54775609566},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"sessionQuotedAsset":{"type":"Session Quoted Asset","name":"","config":"{\n\"initialBalance\": 100\n}","project":"Superalgos","id":"f6cd46c1-66df-422c-82d4-02ac8e37f689","savedPayload":{"position":{"x":27314.957547074417,"y":32638.58168277913},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrame":{"type":"Time Frame","name":"New Time Frame","config":"{ \n\"label\": \"01-min\"\n}","project":"Superalgos","id":"727de4cc-40e6-4064-843c-8cb3a9f2fcdf","savedPayload":{"position":{"x":27418.749983429472,"y":32647.662344319935},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"slippage":{"type":"Slippage","name":"New Slippage","config":"{ \n\"marketOrderRate\": 0.1,\n\"stopLoss\": 0.2,\n\"takeProfit\": 0.3\n}","project":"Superalgos","id":"598dc355-73c9-4e7f-a0e9-ee5fd7952825","savedPayload":{"position":{"x":27513.177200804028,"y":32691.69447891996},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"feeStructure":{"type":"Fee Structure","name":"New Fee Structure","config":"{ \n\"maker\": 0.1,\n\"taker\": 0.1\n}","project":"Superalgos","id":"a3646bab-4d27-48a7-b17c-79d6da48f64d","savedPayload":{"position":{"x":27586.849883185412,"y":32765.367161301343},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"snapshots":{"type":"Snapshots","name":"New Snapshots","config":"{ \n\"strategy\": true,\n\"position\": true\n}","project":"Superalgos","id":"5021a926-442a-4341-8844-8a432293ecb1","savedPayload":{"position":{"x":27630.882017785436,"y":32859.7943786759},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"heartbeats":{"type":"Heartbeats","name":"New Heartbeats","config":"{ \n\"date\": true,\n\"candleIndex\": false\n}","project":"Superalgos","id":"e8cedec0-1bc2-46ba-98de-b7ff746a74c8","savedPayload":{"position":{"x":27639.96267932624,"y":32963.586815030954},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"userDefinedParameters":{"type":"User Defined Parameters","name":"New User Defined Parameters","config":"{ \n\"param1Name\": \"A text string value example\",\n\"param2Name\": 0\n}","project":"Superalgos","id":"67da1d57-62ff-424c-ab2e-034e008fc079","savedPayload":{"position":{"x":27612.99660600971,"y":33064.225570728864},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"726c35b1-e30b-4620-819f-a88a955f1902","savedPayload":{"position":{"x":27341.104269898715,"y":32937.440092206656},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingSystemReference":{"type":"Trading System Reference","name":"Lightning Strike","project":"Superalgos","id":"ff1cd7c1-9415-4c49-8ecf-188fd0c60ea4","savedPayload":{"position":{"x":27428.97223554275,"y":33149.57212656262},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},"tradingEngineReference":{"type":"Trading Engine Reference","name":"Low-Frequency","project":"Superalgos","id":"5fd0a826-0819-4f19-a999-66cc64be0272","savedPayload":{"position":{"x":27341.104269898715,"y":33361.70416091858},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading Engine","name":"Low-Frequency","id":"eb20f622-71bf-4479-a574-d2320e1d4bd1"}}},"id":"1ce123af-467f-4295-b317-dba8729faf25","savedPayload":{"position":{"x":27128.97223554275,"y":33149.57212656262},"targetPosition":{"x":26828.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Resistances and Supports Multi-Period-Daily","project":"Superalgos","id":"0d54601b-fcac-42c9-8ce6-d532bfc81de5","savedPayload":{"position":{"x":26978.97223554275,"y":33409.37974769795},"targetPosition":{"x":26828.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"7e2fdde9-8b64-44a3-85f1-10c3935bd3e3"}}},"id":"4d7e7fa0-afcb-4b2f-983b-ceacea91b29d","savedPayload":{"position":{"x":26828.97223554275,"y":33149.57212656262},"targetPosition":{"x":26569.16461440742,"y":32999.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Trading","id":"a8c8d761-96e5-4a86-9285-6c3881d61442"}}}],"id":"2451fc98-0396-44df-902c-a3eaa90f0618","savedPayload":{"position":{"x":26569.16461440742,"y":32999.57212656262},"targetPosition":{"x":26309.356993272086,"y":32849.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"keyReference":{"type":"Key Reference","name":"Key for Lighting Strike","project":"Superalgos","id":"a0622fc9-c4e3-44c3-963d-7ae5fa163e99","savedPayload":{"position":{"x":26309.356993272086,"y":33149.57212656262},"targetPosition":{"x":26309.356993272086,"y":32849.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Exchange Account Key","name":"Key for Lighting Strike","id":"e85bbbd6-aca8-450f-9237-788062de5761"}}},"id":"c8492c4a-a7a7-4a80-a25a-a610377e6180","savedPayload":{"position":{"x":26309.356993272086,"y":32849.57212656262},"targetPosition":{"x":26159.356993272086,"y":32589.76450542729},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"dd73b670-11d7-4cdc-848b-c063fb7a3848","savedPayload":{"position":{"x":26159.356993272086,"y":32589.76450542729},"targetPosition":{"x":26009.356993272086,"y":32329.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1e087225-153c-4c7e-b9ec-2a36f32ee511","savedPayload":{"position":{"x":26009.356993272086,"y":32329.956884291958},"targetPosition":{"x":25859.356993272086,"y":32070.149263156625},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"013985a8-7bf7-4b91-8e2d-f4e8bd81cb62","savedPayload":{"position":{"x":25859.356993272086,"y":32070.149263156625},"targetPosition":{"x":25709.356993272086,"y":31810.341642021293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"d539c0ac-aaeb-4c44-9dba-ac26df819a8d","savedPayload":{"position":{"x":25709.356993272086,"y":31810.341642021293},"targetPosition":{"x":25559.356993272086,"y":31550.53402088596},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"f4fc305a-6764-427e-86a7-6557118a4b35","savedPayload":{"position":{"x":25559.356993272086,"y":31550.53402088596},"targetPosition":{"x":25409.356993272086,"y":31290.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"673caa5f-511d-4688-9305-e5f0f0f780cd","savedPayload":{"position":{"x":28606.356993272086,"y":29194.726399750627},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataStorage":{"type":"Data Storage","name":"New Data Storage","project":"Superalgos","dataMinesData":{"type":"Data Mines Data","name":"New Data Mines Data","project":"Superalgos","projectDataProducts":[{"type":"Project Data Products","name":"Superalgos","project":"Superalgos","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binanceus","project":"Superalgos","marketDataProducts":[{"type":"Market Data Products","name":"Binanceus BTC/USDT","project":"Superalgos","dataProducts":[],"dataMineProducts":[{"type":"Data Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Candles Volumes","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Candles","project":"Superalgos","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab","savedPayload":{"position":{"x":25635.373168930517,"y":32126.257878002114},"targetPosition":{"x":25538.373168930517,"y":32224.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","project":"Superalgos","id":"07c11481-7dbd-477d-8bf7-79212542a6aa","savedPayload":{"position":{"x":25617.373168930517,"y":32183.257878002114},"targetPosition":{"x":25538.373168930517,"y":32224.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}}],"dataProductFolders":[],"id":"73bb62ff-8212-4387-b160-40ee8de2a133","savedPayload":{"position":{"x":28609.517851064033,"y":30737.271265196097},"targetPosition":{"x":28332.353991310647,"y":30622.46623548657},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Resistances and Supports","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Resistances","project":"Superalgos","id":"a1669770-1bbe-40f7-acb3-ded15272935f","savedPayload":{"position":{"x":25621.373168930517,"y":32076.257878002114},"targetPosition":{"x":25592.373168930517,"y":32158.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Resistances","id":"7a734501-a0fb-4305-803e-7e95d477c513"}}},{"type":"Data Product","name":"Supports","project":"Superalgos","id":"64899503-b618-493a-ba94-bfad2051a611","savedPayload":{"position":{"x":25644.373168930517,"y":32138.257878002114},"targetPosition":{"x":25592.373168930517,"y":32158.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Supports","id":"bc3c43de-6312-47d4-ae3d-0c95c1b039e0"}}}],"dataProductFolders":[],"id":"a1855a09-0948-43de-bba7-8900c5c161d8","savedPayload":{"position":{"x":28371.51184897666,"y":30919.89969389871},"targetPosition":{"x":28332.353991310647,"y":30622.46623548657},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0","savedPayload":{"position":{"x":28332.353991310647,"y":30622.46623548657},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Products","name":"Sparta","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Simple Moving Average (SMA)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Popular SMAs","project":"Superalgos","id":"1b8ea542-14d1-42c0-9af9-c429c308c6fd","savedPayload":{"position":{"x":28043.567704942016,"y":30688.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Popular SMAs","id":"4029d5bf-a8ad-4d80-b874-2af506e0ab34"}}},{"type":"Data Product","name":"Base7 SMAs","project":"Superalgos","id":"589f977c-a9d4-446c-8b5e-ff54250d3b3a","savedPayload":{"position":{"x":28038.567704942016,"y":30670.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base7 SMAs","id":"a03ef0ea-5be9-4d40-952e-24789e77dbb6"}}},{"type":"Data Product","name":"Base11 SMAs","project":"Superalgos","id":"e582bbcc-1d03-4645-8320-acc12afd08cf","savedPayload":{"position":{"x":28120.567704942016,"y":30666.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base11 SMAs","id":"05fabbf9-7798-4a53-995e-53ae74bef3de"}}},{"type":"Data Product","name":"Base5 SMAs","project":"Superalgos","id":"53fe6df8-67cb-4c21-983d-875ea9b532db","savedPayload":{"position":{"x":28117.567704942016,"y":30709.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base5 SMAs","id":"2dcb55de-1673-409e-aa52-f51e7c7f8fa3"}}},{"type":"Data Product","name":"Base6 SMAs","project":"Superalgos","id":"eaaf75ea-2937-460f-87ee-990e632d6475","savedPayload":{"position":{"x":28135.567704942016,"y":30655.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base6 SMAs","id":"4ae22e54-cd02-4e2e-b638-1c5ea9a171ac"}}},{"type":"Data Product","name":"Base12 SMAs","project":"Superalgos","id":"8637a545-6fef-404b-b14f-8f4d11704e57","savedPayload":{"position":{"x":28181.567704942016,"y":30549.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base12 SMAs","id":"723d28e9-a010-48c5-bda0-43a4c2343ddf"}}},{"type":"Data Product","name":"Base30 SMAs","project":"Superalgos","id":"0ce01d0f-adf0-4fe5-961d-037ca8721a97","savedPayload":{"position":{"x":28223.567704942016,"y":30691.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base30 SMAs","id":"607ebabd-9602-4e5c-803d-d4207dbd6794"}}}],"dataProductFolders":[],"id":"f6551bb8-06bd-4873-80b4-d233142c385b","savedPayload":{"position":{"x":28293.196133644633,"y":30919.89969389871},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"MACD 122609","project":"Superalgos","id":"9bc1f567-146e-474e-a12d-942e1f8b8876","savedPayload":{"position":{"x":27977.567704942016,"y":30613.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 122609","id":"6c0c9bf0-90af-4497-b4fb-49b5872b1119"}}},{"type":"Data Product","name":"MACD 031016","project":"Superalgos","id":"e8b6b822-9b76-4559-aefc-957751616417","savedPayload":{"position":{"x":28066.567704942016,"y":30615.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 031016","id":"d1482dc0-e9f1-47ba-b75e-961fa914a53a"}}},{"type":"Data Product","name":"MACD 081709","project":"Superalgos","id":"951914c1-dded-4dda-9f38-c5cc3359c4c0","savedPayload":{"position":{"x":28099.567704942016,"y":30629.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 081709","id":"683e6b29-9f82-4a8e-93eb-20ac0e81a750"}}},{"type":"Data Product","name":"MACD 245209","project":"Superalgos","id":"db2799ed-9bbc-4ba7-87b8-a33efbd513ba","savedPayload":{"position":{"x":28090.567704942016,"y":30512.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 245209","id":"47984765-8180-45cf-a9eb-f0a8b22d165d"}}}],"dataProductFolders":[],"id":"bdee55fc-b907-4378-acba-bd7795cfb8a0","savedPayload":{"position":{"x":28071.409847276,"y":30979.327150223482},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Relative Strenght Index (RSI)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"RSI14","project":"Superalgos","id":"9c42c985-a07d-4892-8853-636d8fec20a0","savedPayload":{"position":{"x":28059.567704942016,"y":30670.89369181134},"targetPosition":{"x":28114.567704942016,"y":30712.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"RSI14","id":"e24248b9-90df-4b26-b5cc-0bac80efa0c7"}}}],"dataProductFolders":[],"id":"3b96186a-c4b9-4409-bf16-2ba82ec6d37c","savedPayload":{"position":{"x":27872.561702854644,"y":30864.522120513957},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"4e954d81-88ad-44b4-9ddf-5930e50d367e","savedPayload":{"position":{"x":28110.567704942016,"y":30681.89369181134},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Products","name":"Alpha","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Stochastic","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Stoch-14-3-3","project":"Superalgos","id":"0ac3f528-2409-45ae-9654-e7dbfd3dbb98","savedPayload":{"position":{"x":27900.719560520658,"y":30610.088662101814},"targetPosition":{"x":27845.719560520658,"y":30534.088662101814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stoch-14-3-3","id":"393dc97b-76ee-409a-9b8f-f264ed652b0b"}}}],"dataProductFolders":[],"id":"8bf2e1e4-cb46-4216-8393-2a6124f3f1f2","savedPayload":{"position":{"x":27673.713558433286,"y":30749.71709080443},"targetPosition":{"x":27911.719560520658,"y":30567.088662101814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"44ad7330-2754-433c-85e7-67bac01affb2","savedPayload":{"position":{"x":27911.719560520658,"y":30567.088662101814},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Alpha","id":"511bef1e-62d8-4ff9-8d87-15bd0d3d630c"}}}],"id":"6d7273da-5366-4fe3-9749-e643038abd7a","savedPayload":{"position":{"x":28149.72556260803,"y":30384.460233399197},"targetPosition":{"x":28188.883420274044,"y":30087.026774987055},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"9bc0aea4-0596-449c-91bd-4fb4cb672aa8","savedPayload":{"position":{"x":28188.883420274044,"y":30087.026774987055},"targetPosition":{"x":28228.041277940058,"y":29789.593316574912},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"db554581-93fa-465d-89f7-50f026e839d8","savedPayload":{"position":{"x":28228.041277940058,"y":29789.593316574912},"targetPosition":{"x":28267.19913560607,"y":29492.15985816277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"32e7c122-fa5a-4d00-9d71-d54e890e32de","savedPayload":{"position":{"x":28267.19913560607,"y":29492.15985816277},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingMinesData":{"type":"Trading Mines Data","name":"New Trading Mines Data","project":"Superalgos","projectTradingProducts":[{"type":"Project Trading Products","name":"Superalgos","project":"Superalgos","exchangeTradingProducts":[{"type":"Exchange Trading Products","name":"Binanceus","project":"Superalgos","marketTradingProducts":[{"type":"Market Trading Products","name":"Binanceus BTC/USDT","project":"Superalgos","tradingSessionReferences":[{"type":"Trading Session Reference","name":"Lightning Strike Backtesting Session","project":"Superalgos","dataProducts":[],"tradingMineProducts":[{"type":"Trading Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Low Frequency","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Engine","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Episode","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading Episode Counters","project":"Superalgos","id":"a01b42b0-ea87-47ab-b0e9-52d4b10cb631","savedPayload":{"position":{"x":24463.592002018682,"y":31980.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Counters","id":"d81c6019-864e-42f5-94ba-2f249b865f85"}}},{"type":"Data Product","name":"Trading Episode Statistics","project":"Superalgos","id":"559a20a7-6697-4245-9d6c-ad7c0e31ff84","savedPayload":{"position":{"x":24313.592002018682,"y":31909.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Statistics","id":"400c7f49-37da-41fb-b83d-879960aa74ff"}}},{"type":"Data Product","name":"Episode Candle","project":"Superalgos","id":"24fab05f-ff78-4cca-af61-d4d0bb2f2960","savedPayload":{"position":{"x":24420.592002018682,"y":31952.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Candle","id":"b9a58113-cf27-4d57-9810-87a2cc158804"}}},{"type":"Data Product","name":"Episode Balances","project":"Superalgos","id":"7c580919-08ce-4aff-9e84-888fdf07caec","savedPayload":{"position":{"x":24281.592002018682,"y":31964.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Balances","id":"a9a53d82-133b-4417-b639-f9a56d338233"}}},{"type":"Data Product","name":"Distance To Trading Event","project":"Superalgos","id":"389797d4-8456-4258-9adf-246a6ba69016","savedPayload":{"position":{"x":24441.592002018682,"y":31984.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Distance To Trading Event","id":"8ea88d6c-7d7f-4152-b781-ea108df52c63"}}},{"type":"Data Product","name":"Episode Base Asset","project":"Superalgos","id":"323c7b0b-42b1-4ff0-9d4b-36c2fd605caa","savedPayload":{"position":{"x":24417.592002018682,"y":31995.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Base Asset","id":"234969ff-eab1-4d59-b6fa-79433c9a20e9"}}},{"type":"Data Product","name":"Episode Quoted Asset","project":"Superalgos","id":"63594fc6-3b89-4507-bca8-2d43ef618cbe","savedPayload":{"position":{"x":24475.592002018682,"y":31901.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Quoted Asset","id":"ae525e31-d6a8-47d2-9021-3f2ddb9615b0"}}},{"type":"Data Product","name":"Current Episode","project":"Superalgos","id":"73bb3f9e-b112-4e5a-bce9-6d4bec41cc6c","savedPayload":{"position":{"x":24306.592002018682,"y":32068.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Episode","id":"b8da0132-ba28-46ec-aa54-eb9eaac56ce7"}}}],"dataProductFolders":[],"id":"a606455e-f5ce-4535-b1af-6d9dd529f91c","savedPayload":{"position":{"x":24377.592002018682,"y":31972.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Strategy","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Strategy","project":"Superalgos","id":"515f5fd6-d860-44d4-b5d6-a19acd9c5c86","savedPayload":{"position":{"x":24475.592002018682,"y":31953.531877463392},"targetPosition":{"x":24454.592002018682,"y":32022.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Strategy","id":"895d8a04-ef45-41a7-909a-ba31013ffb90"}}},{"type":"Data Product","name":"Last Strategy","project":"Superalgos","id":"556e97e8-eba3-419d-869d-950cc99371da","savedPayload":{"position":{"x":24448.592002018682,"y":32071.531877463392},"targetPosition":{"x":24454.592002018682,"y":32022.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Strategy","id":"0625f524-2b97-4b4d-8a90-590ffc62ecd3"}}}],"dataProductFolders":[],"id":"3af0887b-ae23-4f57-b376-4a540fe13112","savedPayload":{"position":{"x":24454.592002018682,"y":32022.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Position","project":"Superalgos","id":"d33abc39-702b-4d7a-8435-43d90e0f2c3a","savedPayload":{"position":{"x":24352.592002018682,"y":32024.531877463392},"targetPosition":{"x":24447.592002018682,"y":32101.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Position","id":"832ecada-8da3-4ba6-b6e9-be34dd5f7ce9"}}},{"type":"Data Product","name":"Last Position","project":"Superalgos","id":"d681fd5f-64af-4f39-9f6d-a767bef7692f","savedPayload":{"position":{"x":24398.592002018682,"y":32035.531877463392},"targetPosition":{"x":24447.592002018682,"y":32101.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Position","id":"477cd6d5-862a-44d0-9313-786a4e63a602"}}}],"dataProductFolders":[],"id":"895feaf2-ae82-4b8e-ada6-780beab73ea9","savedPayload":{"position":{"x":24447.592002018682,"y":32101.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Open Stage","project":"Superalgos","id":"b0961496-1af9-48cd-bbeb-ac5973192e78","savedPayload":{"position":{"x":24555.592002018682,"y":31897.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stage","id":"73c3c041-ba2a-4798-a362-a453409b518a"}}},{"type":"Data Product","name":"Close Stage","project":"Superalgos","id":"0c9cf78d-ce6e-4318-811d-e748ca72845d","savedPayload":{"position":{"x":24541.592002018682,"y":31929.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stage","id":"2bb9bb41-1ff5-4f83-aa5b-bfc4c9f06a9a"}}},{"type":"Data Product","name":"Trigger Stage","project":"Superalgos","id":"e298787f-b7f2-4334-931e-38b9441e43f9","savedPayload":{"position":{"x":24504.592002018682,"y":31961.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stage","id":"b6cff826-9056-4fbd-8eca-cbd6cceec962"}}},{"type":"Data Product","name":"Manage Stage","project":"Superalgos","id":"4719b69d-b23e-4037-8c0a-b641fd8ab14c","savedPayload":{"position":{"x":24444.592002018682,"y":31908.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stage","id":"bd691611-e7a6-49a8-b07d-c15360b55e40"}}}],"dataProductFolders":[],"id":"9fe11205-286a-4610-81ec-29cbc70d6075","savedPayload":{"position":{"x":24520.592002018682,"y":31974.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"90834a1b-cc7e-48a9-be5c-0e30380af4bd","savedPayload":{"position":{"x":24483.592002018682,"y":31990.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"7c769317-2639-4460-8b88-9dc92f7b0585"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"e2112d60-5fc2-4e67-befe-d4fbd6c1de77","savedPayload":{"position":{"x":24491.592002018682,"y":32003.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"9cc7645a-54fe-40d6-9896-9278167011fb"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"e734b6be-ba40-468c-a94f-1153dc85e00c","savedPayload":{"position":{"x":24445.592002018682,"y":32089.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"4c827ee0-a29b-4b65-8438-03e2ea98b410"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"9a973229-4d9d-45af-b5aa-64906a915f6e","savedPayload":{"position":{"x":24422.592002018682,"y":32032.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2c753cd8-36d8-466c-bd80-1ebfa8e314dc"}}},{"type":"Data Product","name":"Last Market Order","project":"Superalgos","id":"56517fe9-64da-4404-83f3-005106bc1c0a","savedPayload":{"position":{"x":24412.592002018682,"y":32018.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Market Order","id":"6df1ac87-92d5-4788-b0bc-f3543b283ef0"}}},{"type":"Data Product","name":"Last Limit Order","project":"Superalgos","id":"d00c76e7-4be0-4518-9892-a0f6df943951","savedPayload":{"position":{"x":24594.592002018682,"y":31949.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Limit Order","id":"c24ec6a1-e937-4d20-93eb-4faf2a0becc3"}}}],"dataProductFolders":[],"id":"b5154bc1-4311-4148-b396-5ebca1c62417","savedPayload":{"position":{"x":24511.592002018682,"y":32023.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"89edd698-1d64-4500-bcef-d13ea74bee1c","savedPayload":{"position":{"x":24421.592002018682,"y":32058.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Trading System","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading System Errors","project":"Superalgos","id":"a0c29c57-0a20-4084-9697-142300f62f9c","savedPayload":{"position":{"x":24383.592002018682,"y":32063.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Errors","id":"1d9c570d-77c7-40ac-a61e-c5a57a411de8"}}},{"type":"Data Product","name":"Trading System Highlights","project":"Superalgos","id":"aa0fe882-89a8-4811-8988-c589554afe9d","savedPayload":{"position":{"x":24294.592002018682,"y":32008.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Highlights","id":"319f660a-78be-4cf4-8052-877837cad806"}}},{"type":"Data Product","name":"Trading System Values","project":"Superalgos","id":"bbc65054-b22b-4cbb-816b-529672e2f498","savedPayload":{"position":{"x":24324.592002018682,"y":32032.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Values","id":"c90c009b-588d-45d4-aff1-05e375181dfa"}}},{"type":"Data Product","name":"Trading System Status","project":"Superalgos","id":"776a3ece-8255-4e80-b60f-85bb818b561f","savedPayload":{"position":{"x":24340.592002018682,"y":32026.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Status","id":"eed48c80-35c5-49fa-b12d-18e7280ffb8f"}}},{"type":"Data Product","name":"Trading System Progress","project":"Superalgos","id":"7593aaf9-0505-4b58-9920-235340ff2d2f","savedPayload":{"position":{"x":24325.592002018682,"y":32003.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Progress","id":"04c8606b-5e59-4e7d-b3ac-387bfffcd300"}}},{"type":"Data Product","name":"Trading System Running","project":"Superalgos","id":"3e2e6105-f41f-42e2-bce5-74ebb3b81cbd","savedPayload":{"position":{"x":24332.592002018682,"y":32039.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Running","id":"17236f59-6ef2-4cc3-913c-1ff6db052236"}}},{"type":"Data Product","name":"Trading System Announcements","project":"Superalgos","id":"faab4399-898b-4393-8c27-fa2f3109c60a","savedPayload":{"position":{"x":24307.592002018682,"y":32057.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Announcements","id":"4a6f828a-9671-431e-8257-fc920943581e"}}},{"type":"Data Product","name":"Trading System Warnings","project":"Superalgos","id":"9ff0f035-ca7f-4e65-a82c-186fa7f09157","savedPayload":{"position":{"x":24297.592002018682,"y":32133.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Warnings","id":"34310596-466a-4e9a-a5a2-256b0fe3e339"}}},{"type":"Data Product","name":"Trading System Infos","project":"Superalgos","id":"04210a59-070a-45f1-a2a0-cf50bd4879f7","savedPayload":{"position":{"x":24389.592002018682,"y":31999.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Infos","id":"020ad519-0fc6-4f2f-9f26-b2c7de118fb8"}}}],"dataProductFolders":[],"id":"1a16bc12-581d-4626-846c-895f08e65fdf","savedPayload":{"position":{"x":24378.592002018682,"y":32060.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Objects","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Episodes","project":"Superalgos","id":"73dff61a-7b05-4ca6-b963-99d6c578e9ba","savedPayload":{"position":{"x":24433.592002018682,"y":31946.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episodes","id":"aeec080e-8caf-4976-8187-ba4e725b73b0"}}},{"type":"Data Product","name":"Strategies","project":"Superalgos","id":"a9c454c8-9075-4dcf-bfe9-ebd0c1658049","savedPayload":{"position":{"x":24490.592002018682,"y":31966.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Strategies","id":"21db6fce-8450-4b07-9015-d81a339fd030"}}}],"dataProductFolders":[{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"cad1eecc-e897-4086-b42c-fcfd843c04cc","savedPayload":{"position":{"x":24570.592002018682,"y":32052.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"db256083-9aa2-48e1-8fd6-3425a5085302"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"fdf22e85-7071-4847-bdba-e3fb43a616ed","savedPayload":{"position":{"x":24567.592002018682,"y":32057.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"1958f79b-5c6c-4874-9154-98c314822ed7"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"d2b1ab31-d8a1-422b-a717-33ee7df9b07b","savedPayload":{"position":{"x":24545.592002018682,"y":31956.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"5deceb32-c7ab-4560-818a-0f0b9d6632fb"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"3b5a12db-b969-4400-8b9d-afb9b7b81642","savedPayload":{"position":{"x":24672.592002018682,"y":31889.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2a1d405b-2fbe-4ed4-a76a-d2c7be59d20e"}}}],"dataProductFolders":[],"id":"97736b8e-761c-43f2-83bf-df8f5d41b963","savedPayload":{"position":{"x":24586.592002018682,"y":31971.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trigger Stages","project":"Superalgos","id":"9fc29be1-9393-4933-95d3-bebddd73c05e","savedPayload":{"position":{"x":24507.592002018682,"y":31875.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stages","id":"18cc2e79-7e57-418c-b635-6c68fc11d681"}}},{"type":"Data Product","name":"Open Stages","project":"Superalgos","id":"b555388f-db93-4db1-91be-7772550afa70","savedPayload":{"position":{"x":24439.592002018682,"y":31926.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stages","id":"d5938c00-0849-466d-ae14-4ea91b571678"}}},{"type":"Data Product","name":"Manage Stages","project":"Superalgos","id":"41953904-e48c-4176-bf0f-09d133bc444c","savedPayload":{"position":{"x":24441.592002018682,"y":31883.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stages","id":"8fab86b3-db8d-4113-8418-1d256bd98cf2"}}},{"type":"Data Product","name":"Close Stages","project":"Superalgos","id":"47b4553c-7f2e-438c-9f4b-9ba30e943a6c","savedPayload":{"position":{"x":24463.592002018682,"y":31931.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stages","id":"ba911e61-f951-48cd-b547-9a70aa211100"}}}],"dataProductFolders":[],"id":"ac789224-64dc-4ff5-a316-2dfbb6347b8a","savedPayload":{"position":{"x":24487.592002018682,"y":31875.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Positions","project":"Superalgos","id":"6e49b57f-8c94-410f-985b-82c126155b11","savedPayload":{"position":{"x":24693.592002018682,"y":31870.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Positions","id":"1eabba24-cbd4-4cbf-95e0-c5135349d41d"}}},{"type":"Data Product","name":"Position Base Asset","project":"Superalgos","id":"ae8fa9a5-95b6-4769-8ade-f9854e6855ba","savedPayload":{"position":{"x":24673.592002018682,"y":32018.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Base Asset","id":"b371b039-f6c8-4f60-84cb-52f55c96c84d"}}},{"type":"Data Product","name":"Position Quoted Asset","project":"Superalgos","id":"9e9b19ee-9c51-4586-b74d-d2880f13f71f","savedPayload":{"position":{"x":24656.592002018682,"y":31987.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Quoted Asset","id":"a376f02b-a5d2-4079-b5cd-ab7dc894b909"}}},{"type":"Data Product","name":"Stop Loss","project":"Superalgos","id":"01491591-0462-453c-91e0-6da6f554a729","savedPayload":{"position":{"x":24536.592002018682,"y":31883.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stop Loss","id":"c18bdc82-216a-4b1d-8850-5c3c9dc2000b"}}},{"type":"Data Product","name":"Take Profit","project":"Superalgos","id":"719dd8a6-58ab-41c6-9693-9b67c12232d2","savedPayload":{"position":{"x":24558.592002018682,"y":31830.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Take Profit","id":"2542c7d0-fa26-4b52-a59a-a3630e52eb89"}}}],"dataProductFolders":[],"id":"2a4cb5a2-8e6a-4b14-816a-b8e0cce4dae5","savedPayload":{"position":{"x":24616.592002018682,"y":31921.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"39e122ca-cdc4-49a6-91a6-2f2c05f62ea0","savedPayload":{"position":{"x":24528.592002018682,"y":31946.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"363150a9-d4e7-4e2e-b327-89109935718c","savedPayload":{"position":{"x":24436.592002018682,"y":31978.531877463392},"targetPosition":{"x":24383.592002018682,"y":32012.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7","savedPayload":{"position":{"x":24383.592002018682,"y":32012.531877463392},"targetPosition":{"x":24343.592002018682,"y":31925.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"a5de30a4-022e-4f8a-afd0-3eb6d8600ae8","savedPayload":{"position":{"x":27706.356993272086,"y":30533.956884291958},"targetPosition":{"x":27706.356993272086,"y":30233.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Trading Session Reference","name":"Lightning Strike Live Trading Session","project":"Superalgos","dataProducts":[],"tradingMineProducts":[{"type":"Trading Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Low Frequency","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Engine","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Episode","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading Episode Counters","project":"Superalgos","id":"dc6cc4ef-4bd7-4837-8442-919462314db3","savedPayload":{"position":{"x":24040.07658106541,"y":32774.458634291004},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Counters","id":"d81c6019-864e-42f5-94ba-2f249b865f85"}}},{"type":"Data Product","name":"Trading Episode Statistics","project":"Superalgos","id":"776ed571-8321-47aa-8cfb-c8ebf565dace","savedPayload":{"position":{"x":24033.260548494378,"y":32904.51628344689},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Statistics","id":"400c7f49-37da-41fb-b83d-879960aa74ff"}}},{"type":"Data Product","name":"Episode Candle","project":"Superalgos","id":"ded93703-a48d-44be-9703-878c28f949cd","savedPayload":{"position":{"x":23982.373237179447,"y":33024.39927619857},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Candle","id":"b9a58113-cf27-4d57-9810-87a2cc158804"}}},{"type":"Data Product","name":"Episode Balances","project":"Superalgos","id":"e702f1dd-1c91-4d05-ac55-19db363f5f3a","savedPayload":{"position":{"x":23893.552407881933,"y":33119.64795433567},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Balances","id":"a9a53d82-133b-4417-b639-f9a56d338233"}}},{"type":"Data Product","name":"Distance To Trading Event","project":"Superalgos","id":"b8abea53-8221-47bd-91a2-cdcdd2ad1027","savedPayload":{"position":{"x":23777.51116347094,"y":33178.77392155408},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Distance To Trading Event","id":"8ea88d6c-7d7f-4152-b781-ea108df52c63"}}},{"type":"Data Product","name":"Episode Base Asset","project":"Superalgos","id":"18bcbd26-c237-4acb-96f4-d9c95d833a42","savedPayload":{"position":{"x":23648.24579060881,"y":33194.6457136009},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Base Asset","id":"234969ff-eab1-4d59-b6fa-79433c9a20e9"}}},{"type":"Data Product","name":"Episode Quoted Asset","project":"Superalgos","id":"c444f4b5-fa67-4c21-afa8-1f998da7a2a2","savedPayload":{"position":{"x":23521.347601016434,"y":33165.348958112605},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Quoted Asset","id":"ae525e31-d6a8-47d2-9021-3f2ddb9615b0"}}},{"type":"Data Product","name":"Current Episode","project":"Superalgos","id":"057570bd-69d4-4f3c-b0d4-94ee32f61e65","savedPayload":{"position":{"x":23412.122389176475,"y":33094.417276175125},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Episode","id":"b8da0132-ba28-46ec-aa54-eb9eaac56ce7"}}}],"dataProductFolders":[],"id":"6a331de0-7872-4f86-bea0-6dd802c97921","savedPayload":{"position":{"x":23667.871774199913,"y":32820.15963806794},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Strategy","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Strategy","project":"Superalgos","id":"88dd680c-a81b-48ae-96ba-838281abfa35","savedPayload":{"position":{"x":23648.24579060881,"y":33194.6457136009},"targetPosition":{"x":23477.99935320648,"y":32860.51826703026},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Strategy","id":"895d8a04-ef45-41a7-909a-ba31013ffb90"}}},{"type":"Data Product","name":"Last Strategy","project":"Superalgos","id":"24af3ffc-6a52-4ee3-a30b-f068aa5b2062","savedPayload":{"position":{"x":23273.759715075845,"y":33175.01973000979},"targetPosition":{"x":23477.99935320648,"y":32860.51826703026},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Strategy","id":"0625f524-2b97-4b4d-8a90-590ffc62ecd3"}}}],"dataProductFolders":[],"id":"74c10f36-887b-4233-81e5-abe365511bfa","savedPayload":{"position":{"x":23477.99935320648,"y":32860.51826703026},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Position","project":"Superalgos","id":"25280962-e4e5-40df-9e42-9edfbad6f6d3","savedPayload":{"position":{"x":23273.759715075845,"y":33175.01973000979},"targetPosition":{"x":23293.38569866695,"y":32800.533654476836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Position","id":"832ecada-8da3-4ba6-b6e9-be34dd5f7ce9"}}},{"type":"Data Product","name":"Last Position","project":"Superalgos","id":"7a95a249-132d-4e0f-9182-cc7af45cacea","savedPayload":{"position":{"x":22959.25825209631,"y":32970.78009187916},"targetPosition":{"x":23293.38569866695,"y":32800.533654476836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Position","id":"477cd6d5-862a-44d0-9313-786a4e63a602"}}}],"dataProductFolders":[],"id":"7eca88a8-3724-4ca1-aa30-9227727eb834","savedPayload":{"position":{"x":23293.38569866695,"y":32800.533654476836},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Open Stage","project":"Superalgos","id":"c9c4bca7-f918-4aa8-b538-ffe8aa31d5c2","savedPayload":{"position":{"x":23104.83496583686,"y":33026.66175662281},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stage","id":"73c3c041-ba2a-4798-a362-a453409b518a"}}},{"type":"Data Product","name":"Close Stage","project":"Superalgos","id":"4201d7c0-43aa-4ac0-bd7e-ab26b688aa2d","savedPayload":{"position":{"x":22898.332847281992,"y":32921.44367184458},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stage","id":"2bb9bb41-1ff5-4f83-aa5b-bfc4c9f06a9a"}}},{"type":"Data Product","name":"Trigger Stage","project":"Superalgos","id":"4fe24ddc-973f-4a5d-bf8a-d77090486125","savedPayload":{"position":{"x":22793.11476250377,"y":32714.941553289715},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stage","id":"b6cff826-9056-4fbd-8eca-cbd6cceec962"}}},{"type":"Data Product","name":"Manage Stage","project":"Superalgos","id":"e2f3d69e-2f0a-4463-8e74-4f0768c4fb70","savedPayload":{"position":{"x":22829.37044365631,"y":32486.0321914973},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stage","id":"bd691611-e7a6-49a8-b07d-c15360b55e40"}}}],"dataProductFolders":[],"id":"7236bd16-a6e3-48ac-89bf-dc8674b7e812","savedPayload":{"position":{"x":23163.497890226947,"y":32656.27862889963},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"0e0b284a-5014-4ab0-ada0-4322c14a099e","savedPayload":{"position":{"x":22942.973442347367,"y":32795.291108279984},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"7c769317-2639-4460-8b88-9dc92f7b0585"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"95b3db7a-9b62-4eab-a76b-4af8794da5a6","savedPayload":{"position":{"x":22818.117657046547,"y":32684.55024509317},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"9cc7645a-54fe-40d6-9896-9278167011fb"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"1c6eed42-23aa-4174-aade-be29222acb8c","savedPayload":{"position":{"x":22753.675141305597,"y":32530.603279980434},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"4c827ee0-a29b-4b65-8438-03e2ea98b410"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"a2f44cd5-090d-42e5-9eb7-73e732310e85","savedPayload":{"position":{"x":22762.409525702606,"y":32363.941297417976},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2c753cd8-36d8-466c-bd80-1ebfa8e314dc"}}},{"type":"Data Product","name":"Last Market Order","project":"Superalgos","id":"8c24d559-ba52-46fe-81b4-8a6bf50c74b6","savedPayload":{"position":{"x":22842.590858287545,"y":32217.573747027367},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Market Order","id":"6df1ac87-92d5-4788-b0bc-f3543b283ef0"}}},{"type":"Data Product","name":"Last Limit Order","project":"Superalgos","id":"c451c035-5ece-451f-836f-b5334cb3f967","savedPayload":{"position":{"x":22978.338242782465,"y":32120.49051724367},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Limit Order","id":"c24ec6a1-e937-4d20-93eb-4faf2a0becc3"}}}],"dataProductFolders":[],"id":"ce9593a8-3e87-43bb-88c7-af50cf651806","savedPayload":{"position":{"x":23123.13926126462,"y":32466.406207906195},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8be94a26-6821-48bb-8169-3eae2a1131af","savedPayload":{"position":{"x":23497.625336797584,"y":32486.0321914973},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Trading System","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading System Errors","project":"Superalgos","id":"ba606f99-2ae5-44dc-b7db-399e657830e1","savedPayload":{"position":{"x":23295.861450927674,"y":32622.443323337528},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Errors","id":"1d9c570d-77c7-40ac-a61e-c5a57a411de8"}}},{"type":"Data Product","name":"Trading System Highlights","project":"Superalgos","id":"2d20d8ae-4afa-4e92-8de2-89e66e5efdee","savedPayload":{"position":{"x":23182.53338349962,"y":32592.0771591904},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Highlights","id":"319f660a-78be-4cf4-8052-877837cad806"}}},{"type":"Data Product","name":"Trading System Values","project":"Superalgos","id":"f8a6219c-c7b4-410a-8aa4-1910583f51c8","savedPayload":{"position":{"x":23084.13564726847,"y":32528.17692212845},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Values","id":"c90c009b-588d-45d4-aff1-05e375181dfa"}}},{"type":"Data Product","name":"Trading System Status","project":"Superalgos","id":"dcff6f56-7646-4505-aa93-6682a110f3f2","savedPayload":{"position":{"x":23010.300098233878,"y":32436.997612574425},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Status","id":"eed48c80-35c5-49fa-b12d-18e7280ffb8f"}}},{"type":"Data Product","name":"Trading System Progress","project":"Superalgos","id":"0a9dff80-e462-4110-b988-11ce57bbbcd5","savedPayload":{"position":{"x":22968.25427437787,"y":32327.464496631084},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Progress","id":"04c8606b-5e59-4e7d-b3ac-387bfffcd300"}}},{"type":"Data Product","name":"Trading System Running","project":"Superalgos","id":"c7e05ad0-7d4a-4ffb-9aee-191511f85ee7","savedPayload":{"position":{"x":22962.11391388994,"y":32210.299438849055},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Running","id":"17236f59-6ef2-4cc3-913c-1ff6db052236"}}},{"type":"Data Product","name":"Trading System Announcements","project":"Superalgos","id":"e4811789-fd94-49b0-9917-8d9d434f997d","savedPayload":{"position":{"x":22992.480078037068,"y":32096.971371421},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Announcements","id":"4a6f828a-9671-431e-8257-fc920943581e"}}},{"type":"Data Product","name":"Trading System Warnings","project":"Superalgos","id":"029ff3a7-9c65-425f-855a-882df68fa05b","savedPayload":{"position":{"x":23056.38031509902,"y":31998.573635189852},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Warnings","id":"34310596-466a-4e9a-a5a2-256b0fe3e339"}}},{"type":"Data Product","name":"Trading System Infos","project":"Superalgos","id":"0f47adaf-25a0-431f-b15b-0fbf44069b38","savedPayload":{"position":{"x":23147.559624653044,"y":31924.73808615526},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Infos","id":"020ad519-0fc6-4f2f-9f26-b2c7de118fb8"}}}],"dataProductFolders":[],"id":"7096a712-deb7-4adb-86e0-d688f24d2832","savedPayload":{"position":{"x":23335.059624653044,"y":32249.497612574425},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Objects","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Episodes","project":"Superalgos","id":"c6fd6067-4b57-4860-ae3b-5668e4444490","savedPayload":{"position":{"x":23053.23606537805,"y":32137.53752778946},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episodes","id":"aeec080e-8caf-4976-8187-ba4e725b73b0"}}},{"type":"Data Product","name":"Strategies","project":"Superalgos","id":"60f88096-7343-42d1-afad-83fecd22fb44","savedPayload":{"position":{"x":23012.87743641572,"y":31947.665106796027},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Strategies","id":"21db6fce-8450-4b07-9015-d81a339fd030"}}}],"dataProductFolders":[{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"9f939086-c934-4924-8353-776707a7cf10","savedPayload":{"position":{"x":22722.769389032703,"y":31897.43943333598},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"db256083-9aa2-48e1-8fd6-3425a5085302"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"da5f279e-d387-43cf-80f4-fc114b9ac906","savedPayload":{"position":{"x":22710.63986411075,"y":31665.99431034305},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"1958f79b-5c6c-4874-9154-98c314822ed7"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"367646bb-839a-4071-8305-6d26a647585d","savedPayload":{"position":{"x":22836.866902325462,"y":31471.62171671013},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"5deceb32-c7ab-4560-818a-0f0b9d6632fb"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"0b2fc73a-9635-40b2-98d8-0c79c69175a9","savedPayload":{"position":{"x":23053.23606537805,"y":31388.56537672353},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2a1d405b-2fbe-4ed4-a76a-d2c7be59d20e"}}}],"dataProductFolders":[],"id":"88643ab2-7859-45d4-b967-8681cf970828","savedPayload":{"position":{"x":23072.862048969153,"y":31763.051452256495},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trigger Stages","project":"Superalgos","id":"7fe8c58f-9cad-47c9-ba4e-d66bff094dcf","savedPayload":{"position":{"x":22846.73394682318,"y":31574.500719426407},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stages","id":"18cc2e79-7e57-418c-b635-6c68fc11d681"}}},{"type":"Data Product","name":"Open Stages","project":"Superalgos","id":"41f17745-1819-4681-8a2b-9bdda3cd67c4","savedPayload":{"position":{"x":22951.952031601402,"y":31367.99860087154},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stages","id":"d5938c00-0849-466d-ae14-4ea91b571678"}}},{"type":"Data Product","name":"Manage Stages","project":"Superalgos","id":"e89c8bfd-fac9-4aff-afc0-3a89c1dc2710","savedPayload":{"position":{"x":23158.45415015627,"y":31262.780516093317},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stages","id":"8fab86b3-db8d-4113-8418-1d256bd98cf2"}}},{"type":"Data Product","name":"Close Stages","project":"Superalgos","id":"bc2c6503-e935-4ad7-a76a-89b062d41e91","savedPayload":{"position":{"x":23387.363511948686,"y":31299.036197245856},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stages","id":"ba911e61-f951-48cd-b547-9a70aa211100"}}}],"dataProductFolders":[],"id":"869369c1-13de-4086-ad40-77b3d54cfc36","savedPayload":{"position":{"x":23217.117074546357,"y":31633.163643816493},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Positions","project":"Superalgos","id":"3ed594a0-8452-4bd8-9eaa-37cd83a45b90","savedPayload":{"position":{"x":23092.488032560257,"y":31388.56537672353},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Positions","id":"1eabba24-cbd4-4cbf-95e0-c5135349d41d"}}},{"type":"Data Product","name":"Position Base Asset","project":"Superalgos","id":"88997c97-e77f-490e-9eb5-c7531beec132","savedPayload":{"position":{"x":23236.74305813746,"y":31258.67756828353},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Base Asset","id":"b371b039-f6c8-4f60-84cb-52f55c96c84d"}}},{"type":"Data Product","name":"Position Quoted Asset","project":"Superalgos","id":"b4772611-d5d0-4fbd-b689-d42de3c045d4","savedPayload":{"position":{"x":23426.615479130895,"y":31218.3189393212},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Quoted Asset","id":"a376f02b-a5d2-4079-b5cd-ab7dc894b909"}}},{"type":"Data Product","name":"Stop Loss","project":"Superalgos","id":"9b064960-3829-441f-b955-334fb8324a53","savedPayload":{"position":{"x":23611.229133670426,"y":31278.303551874633},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stop Loss","id":"c18bdc82-216a-4b1d-8850-5c3c9dc2000b"}}},{"type":"Data Product","name":"Take Profit","project":"Superalgos","id":"cbcc817b-4333-4c80-addc-e2a0ee0845c1","savedPayload":{"position":{"x":23741.116942110428,"y":31422.558577451837},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Take Profit","id":"2542c7d0-fa26-4b52-a59a-a3630e52eb89"}}}],"dataProductFolders":[],"id":"7f74f2e1-91b6-4d7a-87cb-1d6232a41876","savedPayload":{"position":{"x":23406.98949553979,"y":31592.805014854166},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"291949a0-847b-4b18-b3b4-191496fc38a9","savedPayload":{"position":{"x":23387.363511948686,"y":31967.29109038713},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ae78f4fc-6ee5-4ae4-9847-3bab0e2e51a6","savedPayload":{"position":{"x":23701.86497492822,"y":32171.530728517766},"targetPosition":{"x":24068.670325203395,"y":32093.563844461107},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"aa2b0766-a3d5-47e1-acd8-7345af564388","savedPayload":{"position":{"x":24068.670325203395,"y":32093.563844461107},"targetPosition":{"x":24313.207225386846,"y":32041.58592175667},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"9ef30086-0c9d-47c2-8983-db5fc9a99583","savedPayload":{"position":{"x":27446.549372136753,"y":30383.956884291958},"targetPosition":{"x":27706.356993272086,"y":30233.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Live Trading Session","name":"Lightning Strike","id":"1ce123af-467f-4295-b317-dba8729faf25"}}}],"id":"026bab29-64d0-4d83-862c-446657efa101","savedPayload":{"position":{"x":27706.356993272086,"y":30233.956884291958},"targetPosition":{"x":27856.356993272086,"y":29974.149263156625},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"f601d2a7-fada-477f-9b63-3ef7ed42d44a","savedPayload":{"position":{"x":27856.356993272086,"y":29974.149263156625},"targetPosition":{"x":28006.356993272086,"y":29714.341642021293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"691abc38-257f-462f-bee5-1cc51d77cea6","savedPayload":{"position":{"x":28006.356993272086,"y":29714.341642021293},"targetPosition":{"x":28156.356993272086,"y":29454.53402088596},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"e4e268f3-a677-4f90-90a1-d87244e647e5","savedPayload":{"position":{"x":28156.356993272086,"y":29454.53402088596},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"learningMinesData":{"type":"Learning Mines Data","name":"New Learning Mines Data","project":"Superalgos","projectLearningProducts":[{"type":"Project Learning Products","name":"Superalgos","project":"Superalgos","exchangeLearningProducts":[],"id":"071c1c13-0e4c-4649-b2eb-7dc422278961","savedPayload":{"position":{"x":27830.344989097342,"y":29559.98325715586},"targetPosition":{"x":28068.350991184714,"y":29377.354828453244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"2845a687-becc-4c3b-bc79-b2293ba876ba","savedPayload":{"position":{"x":28068.350991184714,"y":29377.354828453244},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e2697759-6038-4943-b90c-5a68651ff9a8","savedPayload":{"position":{"x":28306.356993272086,"y":29194.726399750627},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"d"}}},"id":"e452cf65-2b2b-44f2-9e67-bdd9d3c008e4","savedPayload":{"position":{"x":28456.356993272086,"y":28934.918778615294},"targetPosition":{"x":28156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""}}}],"id":"3c165071-7558-4708-9999-8ffe71d346b1","savedPayload":{"position":{"x":28156.356993272086,"y":28934.918778615294},"targetPosition":{"x":28156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"s"}}},{"type":"Crypto Ecosystem","name":"My Crypto Ecosystem","project":"Superalgos","cryptoExchanges":[{"type":"Crypto Exchanges","name":"Tested","project":"Superalgos","exchanges":[{"type":"Crypto Exchange","name":"Binanceus","config":"{\n \"codeName\": \"binanceus\",\n \"API\": [\n {\n \"method\": \"fetchTrades\",\n \"fetchType\": \"by Id\",\n \"fetchTradesMethod\": \"publicGetHistoricalTrades\",\n \"firstId\": \"f\"\n }\n ]\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"EUR\"} \n}","project":"Superalgos","assets":[{"type":"Asset","name":"Bitcoin","config":"{ \n\"codeName\": \"BTC\"\n}","project":"Superalgos","id":"5f5e4a94-5090-47d4-8883-cc2325d20bfa","savedPayload":{"position":{"x":19793.079365950267,"y":30513.325102172115},"targetPosition":{"x":19715.43365241951,"y":30803.102850058836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Asset","name":"Tether","config":"{ \n\"codeName\": \"USDT\"\n}","project":"Superalgos","id":"f110bfa0-bd5b-469b-a940-4524c8688136","savedPayload":{"position":{"x":20005.21140030623,"y":30725.45713652808},"targetPosition":{"x":19715.43365241951,"y":30803.102850058836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"id":"95d2c30f-215b-486e-8119-f4eac0279575","savedPayload":{"position":{"x":19715.43365241951,"y":30803.102850058836},"targetPosition":{"x":19503.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"E"}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","code":"{ \n\"codeName\": \"Write here the code name of the Market here.\"\n}","project":"Superalgos","markets":[{"type":"Market","name":"BTC/USDT","config":"{ \n\"codeName\": \"BTC/USDT\"\n}","project":"Superalgos","baseAsset":{"type":"Market Base Asset","name":"Bitcoin","project":"Superalgos","id":"1017b30d-de1b-4212-991e-9fd0a5b6c814","savedPayload":{"position":{"x":20393.079365950267,"y":30937.589170884043},"targetPosition":{"x":20103.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Asset","name":"Bitcoin","id":"5f5e4a94-5090-47d4-8883-cc2325d20bfa"}}},"quotedAsset":{"type":"Market Quoted Asset","name":"Tether","project":"Superalgos","id":"705c4a67-787a-48cd-a3dc-3a557438bf0b","savedPayload":{"position":{"x":20393.079365950267,"y":31092.880597945557},"targetPosition":{"x":20103.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Asset","name":"Tether","id":"f110bfa0-bd5b-469b-a940-4524c8688136"}}},"id":"9a867bf0-a71d-445c-b99a-75b60bbdce09","savedPayload":{"position":{"x":20103.301618063546,"y":31015.2348844148},"targetPosition":{"x":19803.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2fd80894-900e-44ac-a1a7-56c14124f7a1","savedPayload":{"position":{"x":19803.301618063546,"y":31015.2348844148},"targetPosition":{"x":19503.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b","savedPayload":{"position":{"x":19503.301618063546,"y":31015.2348844148},"targetPosition":{"x":19203.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""},"tutorial":{"status":"Done"}}}],"id":"e3879d63-6f8f-41a3-8ac3-0349c4361722","savedPayload":{"position":{"x":19203.301618063546,"y":31015.2348844148},"targetPosition":{"x":18903.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchanges","name":"Untested","project":"Superalgos","exchanges":[{"type":"Crypto Exchange","name":"ACX","config":"{ \n\"codeName\": \"acx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"ebcb522b-ae58-46d2-9d82-a9b0beec3976","savedPayload":{"position":{"x":17935.64382962515,"y":31014.23747069523},"targetPosition":{"x":17912.64382962515,"y":30954.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b2649588-27c6-442c-b179-f6d8817188b3","savedPayload":{"position":{"x":17954.64382962515,"y":31004.23747069523},"targetPosition":{"x":17912.64382962515,"y":30954.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e9c21b2d-de21-43b5-8b48-51367a8c981c","savedPayload":{"position":{"x":19313.14497226101,"y":30565.583066825377},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"AOFEX","config":"{ \n\"codeName\": \"aofex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"623ef91b-04c0-4bd5-ac0d-b32c809be3ea","savedPayload":{"position":{"x":17973.64382962515,"y":30923.23747069523},"targetPosition":{"x":17950.64382962515,"y":30994.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"9d0b5855-59a6-4dda-9a4b-33d7a44d582e","savedPayload":{"position":{"x":17901.64382962515,"y":30994.23747069523},"targetPosition":{"x":17950.64382962515,"y":30994.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c2e9bb45-97c7-47e8-b13c-56946e673c53","savedPayload":{"position":{"x":19413.67778623216,"y":30647.89853748846},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bequant","config":"{ \n\"codeName\": \"bequant\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"b23c8adf-c880-48fd-b4af-4b4be86cf0e5","savedPayload":{"position":{"x":18059.64382962515,"y":31101.23747069523},"targetPosition":{"x":17960.64382962515,"y":31060.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"523bd94f-68f9-457e-91fd-806c1b95e98d","savedPayload":{"position":{"x":18006.64382962515,"y":31117.23747069523},"targetPosition":{"x":17960.64382962515,"y":31060.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8e928d3e-a2c2-4341-aa2f-b753551c9479","savedPayload":{"position":{"x":19504.72140465123,"y":30740.600980501622},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bibox","config":"{ \n\"codeName\": \"bibox\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"13c1f22c-9a35-4d3f-b000-c96984fd6a2b","savedPayload":{"position":{"x":17995.64382962515,"y":31047.23747069523},"targetPosition":{"x":17929.64382962515,"y":31003.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3c6df49d-70c3-468a-bdd8-6768ce6d3a9d","savedPayload":{"position":{"x":17916.64382962515,"y":31018.23747069523},"targetPosition":{"x":17929.64382962515,"y":31003.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e5f9ee4d-77a3-48ae-b354-b2f6a97d5e47","savedPayload":{"position":{"x":19585.208424334218,"y":30842.603544479174},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BigONE","config":"{ \n\"codeName\": \"bigone\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"3f289513-c1c8-457c-b65a-8cf62b5f5eb5","savedPayload":{"position":{"x":17778.64382962515,"y":31071.23747069523},"targetPosition":{"x":17839.64382962515,"y":31063.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8b365e73-1cee-496a-921f-121cb628a130","savedPayload":{"position":{"x":17798.64382962515,"y":31121.23747069523},"targetPosition":{"x":17839.64382962515,"y":31063.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fb9ee540-bf12-4dda-bf87-cb6b58fce649","savedPayload":{"position":{"x":19654.195208565325,"y":30952.710342620318},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Binance Jersey","config":"{ \n\"codeName\": \"binanceje\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"0b979ea9-7a2d-4744-9517-2dfa632dfafc","savedPayload":{"position":{"x":17852.64382962515,"y":30989.23747069523},"targetPosition":{"x":17933.64382962515,"y":30992.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b9a4497d-20f1-4c61-9a79-444e0fe0ddf4","savedPayload":{"position":{"x":17924.64382962515,"y":30952.23747069523},"targetPosition":{"x":17933.64382962515,"y":30992.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"2782350a-84a2-40ec-87c6-3c8043376a18","savedPayload":{"position":{"x":19710.872950374665,"y":31069.630473388454},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Binance US","config":"{ \n\"codeName\": \"binanceus\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"817ee1cf-b44c-4458-a9c4-a05a17ea0510","savedPayload":{"position":{"x":17943.64382962515,"y":30999.23747069523},"targetPosition":{"x":17898.64382962515,"y":31020.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c6694e9e-74dc-4c2e-9151-90f1d6631b45","savedPayload":{"position":{"x":17937.64382962515,"y":30989.23747069523},"targetPosition":{"x":17898.64382962515,"y":31020.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0b2b67d2-853b-470e-8b13-925956ad5621","savedPayload":{"position":{"x":19754.577155060477,"y":31191.993155151424},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"bitbank","config":"{ \n\"codeName\": \"bitbank\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"eb6b6842-9bf7-450e-baa3-7a87541a1cf6","savedPayload":{"position":{"x":17955.64382962515,"y":31107.23747069523},"targetPosition":{"x":17941.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"6353ff56-759f-457d-81f3-fdb8ae5b3e83","savedPayload":{"position":{"x":17942.64382962515,"y":31183.23747069523},"targetPosition":{"x":17941.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6c9a96a7-ed12-4b3e-bb51-306a8da131f5","savedPayload":{"position":{"x":19784.79543078195,"y":31318.363797342816},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitBay","config":"{ \n\"codeName\": \"bitbay\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"83b4e523-72a7-41ce-9363-fe0c799dcac1","savedPayload":{"position":{"x":17861.64382962515,"y":30965.23747069523},"targetPosition":{"x":17855.64382962515,"y":30961.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"966698f7-8a28-42d7-bb80-f7cd0601e44f","savedPayload":{"position":{"x":17823.64382962515,"y":31026.23747069523},"targetPosition":{"x":17855.64382962515,"y":30961.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8778eee5-97a2-4f9d-bd25-cd5a64ec6663","savedPayload":{"position":{"x":19801.173495885087,"y":31447.26081972472},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitfinex","config":"{ \n\"codeName\": \"bitfinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"33508b53-2769-4f3d-8c98-9fa37e5cbf5b","savedPayload":{"position":{"x":17888.64382962515,"y":31043.23747069523},"targetPosition":{"x":17965.64382962515,"y":30956.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4d4ad5a1-81a7-4f92-83db-99f57ce261bb","savedPayload":{"position":{"x":17975.64382962515,"y":30868.23747069523},"targetPosition":{"x":17965.64382962515,"y":30956.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6c076027-683d-4778-8a6a-e60984980fdf","savedPayload":{"position":{"x":19803.51933253116,"y":31577.173022561386},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitfinex","config":"{ \n\"codeName\": \"bitfinex2\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"8fc7f955-5c81-446c-bbeb-205988bf1fc0","savedPayload":{"position":{"x":17830.64382962515,"y":31051.23747069523},"targetPosition":{"x":17863.64382962515,"y":31062.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d5ba38e9-3282-4634-b922-16532c71f426","savedPayload":{"position":{"x":17819.64382962515,"y":31118.23747069523},"targetPosition":{"x":17863.64382962515,"y":31062.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"f3114102-a73c-4086-9594-5888ef1ab4ec","savedPayload":{"position":{"x":19791.80543793031,"y":31706.577304054405},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitforex","config":"{ \n\"codeName\": \"bitforex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"698e5e38-ad73-4cb6-b7f6-2b69913faff9","savedPayload":{"position":{"x":17897.64382962515,"y":30956.23747069523},"targetPosition":{"x":17937.64382962515,"y":30945.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"f0142bd4-1b63-4d12-a4b7-e150d0da197f","savedPayload":{"position":{"x":18020.64382962515,"y":31021.23747069523},"targetPosition":{"x":17937.64382962515,"y":30945.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"499a5a3b-7871-4c95-9b2e-d58d4d9e2392","savedPayload":{"position":{"x":19766.169146786622,"y":31833.956517318737},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"bitkk","config":"{ \n\"codeName\": \"bitkk\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"efbb916c-780b-447f-a4c2-df68570d4ee1","savedPayload":{"position":{"x":17931.64382962515,"y":30937.23747069523},"targetPosition":{"x":17951.64382962515,"y":30936.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0d829516-81d9-46a5-9861-7d94cc89455d","savedPayload":{"position":{"x":17951.64382962515,"y":30912.23747069523},"targetPosition":{"x":17951.64382962515,"y":30936.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ded39740-3c93-4fda-bb9c-6ac75d2109f4","savedPayload":{"position":{"x":19726.911021174266,"y":31957.817257542785},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMart","config":"{ \n\"codeName\": \"bitmart\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"10374855-6b4a-460b-9c95-70072ac00315","savedPayload":{"position":{"x":17907.64382962515,"y":30901.23747069523},"targetPosition":{"x":17834.64382962515,"y":30915.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3aded60c-4061-48ff-ad33-212c965b5c43","savedPayload":{"position":{"x":17829.64382962515,"y":30925.23747069523},"targetPosition":{"x":17834.64382962515,"y":30915.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c7ed52a7-895b-46f1-a745-35954d8bcfc6","savedPayload":{"position":{"x":19674.491326722004,"y":32076.707370794375},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMax","config":"{ \n\"codeName\": \"bitmax\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"8a042d0d-7a7a-4a76-889e-42d8642404f4","savedPayload":{"position":{"x":17944.64382962515,"y":31046.23747069523},"targetPosition":{"x":17944.64382962515,"y":31109.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0c4fcc48-51e6-4ff2-925f-405cda6d1122","savedPayload":{"position":{"x":17898.64382962515,"y":31024.23747069523},"targetPosition":{"x":17944.64382962515,"y":31109.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fc6a9048-ab8c-48f9-91ae-6c95c28714b0","savedPayload":{"position":{"x":19609.524636419505,"y":32189.2329791979},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMEX","config":"{ \n\"codeName\": \"bitmex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f7636e2b-354a-4217-894b-5e26eddc0c2a","savedPayload":{"position":{"x":17894.64382962515,"y":30934.23747069523},"targetPosition":{"x":17910.64382962515,"y":30922.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"6eb2ddd1-6d06-456c-b4e0-7df56ba182e6","savedPayload":{"position":{"x":17823.64382962515,"y":30834.23747069523},"targetPosition":{"x":17910.64382962515,"y":30922.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"1e2f1dd0-ebf1-4485-83d8-7723a9e3e714","savedPayload":{"position":{"x":19532.77262531095,"y":32294.07482287797},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bittrex","config":"{ \n\"codeName\": \"bittrex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"88d4ef94-f030-42df-9115-69d9611317b1","savedPayload":{"position":{"x":17839.64382962515,"y":31009.23747069523},"targetPosition":{"x":17893.64382962515,"y":30968.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"7fe8234d-9a39-4b28-bf98-43b4fdb57ee5","savedPayload":{"position":{"x":17878.64382962515,"y":31045.23747069523},"targetPosition":{"x":17893.64382962515,"y":30968.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"f598f002-8fc5-491f-888e-07d017ea83c6","savedPayload":{"position":{"x":19445.135140551556,"y":32390.003727075255},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bit-Z","config":"{ \n\"codeName\": \"bitz\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"0a22e02b-7d2e-4955-9cfc-ed7d95f0c9a0","savedPayload":{"position":{"x":17751.64382962515,"y":31083.23747069523},"targetPosition":{"x":17850.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"298b45af-b73d-4cd5-848a-97de7b857569","savedPayload":{"position":{"x":17944.64382962515,"y":31083.23747069523},"targetPosition":{"x":17850.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6cc10926-fe41-43be-887b-fa8aba1c7377","savedPayload":{"position":{"x":19347.639651522415,"y":32475.89501309667},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BTC-Alpha","config":"{ \n\"codeName\": \"btcalpha\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"263e3b9c-8fdd-4376-b53b-87f32d0f5898","savedPayload":{"position":{"x":17904.64382962515,"y":30922.23747069523},"targetPosition":{"x":17883.64382962515,"y":30971.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"804603e1-3e0f-4219-a9b7-ee27810d4f07","savedPayload":{"position":{"x":17829.64382962515,"y":30977.23747069523},"targetPosition":{"x":17883.64382962515,"y":30971.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"30e5485f-213b-435b-a670-07b76cfe5cae","savedPayload":{"position":{"x":19241.429203691412,"y":32550.741684144767},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BTC Markets","config":"{ \n\"codeName\": \"btcmarkets\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"fcb3b880-0852-4d93-8714-67373f9dca16","savedPayload":{"position":{"x":17911.64382962515,"y":31036.23747069523},"targetPosition":{"x":17994.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"953d8eff-0b2e-4b07-8635-393fddae0c9d","savedPayload":{"position":{"x":18025.64382962515,"y":31127.23747069523},"targetPosition":{"x":17994.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ac2fda42-95ca-404a-8dd2-72bff0ff5a0f","savedPayload":{"position":{"x":19127.749017450227,"y":32613.66623143447},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Buda","config":"{ \n\"codeName\": \"buda\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"27f3573d-e1f0-473f-9bfd-f9198e7240a0","savedPayload":{"position":{"x":17945.64382962515,"y":30937.23747069523},"targetPosition":{"x":17853.64382962515,"y":31005.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4ddc0981-4e45-42f3-ae11-f5b136b2bc3d","savedPayload":{"position":{"x":17783.64382962515,"y":31008.23747069523},"targetPosition":{"x":17853.64382962515,"y":31005.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"90fe3d74-662e-4fac-aff3-f41990b61ccf","savedPayload":{"position":{"x":19007.931889043757,"y":32663.930922181273},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BW","config":"{ \n\"codeName\": \"bw\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"457616cd-25f9-4ad3-8c18-6331859dd42e","savedPayload":{"position":{"x":17890.64382962515,"y":31014.23747069523},"targetPosition":{"x":17900.64382962515,"y":30965.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8c1f9aa2-4253-4129-a533-e515644ddb38","savedPayload":{"position":{"x":17909.64382962515,"y":30970.23747069523},"targetPosition":{"x":17900.64382962515,"y":30965.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d72db90c-d572-4cbb-8348-e3cc485d8e86","savedPayload":{"position":{"x":18883.38256475272,"y":32700.94644884361},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bybit","config":"{ \n\"codeName\": \"bybit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"18fdf7c8-03c4-4f81-a88e-de97589765e1","savedPayload":{"position":{"x":17803.64382962515,"y":31059.23747069523},"targetPosition":{"x":17855.64382962515,"y":31007.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"a62b2603-ac6f-4b6e-9541-86daf32027b1","savedPayload":{"position":{"x":17847.64382962515,"y":31104.23747069523},"targetPosition":{"x":17855.64382962515,"y":31007.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"516c3831-456b-4d17-b0a0-6a363ba2ddb2","savedPayload":{"position":{"x":18755.561271527895,"y":32724.27883821499},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"ByteTrade","config":"{ \n\"codeName\": \"bytetrade\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e7a1e531-5a9e-466e-b98d-672de39eed3a","savedPayload":{"position":{"x":18088.64382962515,"y":31024.23747069523},"targetPosition":{"x":17991.64382962515,"y":30981.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"edafaba7-fd82-4d9f-b3f7-5d1c01c56599","savedPayload":{"position":{"x":17941.64382962515,"y":30943.23747069523},"targetPosition":{"x":17991.64382962515,"y":30981.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"45e2306f-03e8-4d17-a73a-72c11dd14e78","savedPayload":{"position":{"x":18625.966597164217,"y":32733.65453936303},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CEX.IO","config":"{ \n\"codeName\": \"cex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9de19f0a-5824-4e42-af00-484b64421dc3","savedPayload":{"position":{"x":17890.64382962515,"y":31049.23747069523},"targetPosition":{"x":17896.64382962515,"y":31076.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"39db01bc-0cea-422f-b9e9-7d84e3f5446d","savedPayload":{"position":{"x":17918.64382962515,"y":31105.23747069523},"targetPosition":{"x":17896.64382962515,"y":31076.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"346bfc30-e32a-453a-bdc6-0ead48221581","savedPayload":{"position":{"x":18496.117920729066,"y":32728.96363076407},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Coinbase Prime","config":"{ \n\"codeName\": \"coinbaseprime\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"73cabd8d-9308-49ed-b544-44f785ee7d38","savedPayload":{"position":{"x":17867.64382962515,"y":30962.23747069523},"targetPosition":{"x":17922.64382962515,"y":30960.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"31bd1360-f0c5-4d70-876a-b152f7cedfd7","savedPayload":{"position":{"x":17960.64382962515,"y":30864.23747069523},"targetPosition":{"x":17922.64382962515,"y":30960.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5a8281db-6ace-4186-8cfb-cd249c4af48b","savedPayload":{"position":{"x":18367.537599231866,"y":32710.26110903248},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Coinbase Pro","config":"{ \n\"codeName\": \"coinbasepro\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"a29d6e1a-a94e-4b6b-8741-e9af6e4762f4","savedPayload":{"position":{"x":17788.64382962515,"y":30897.23747069523},"targetPosition":{"x":17841.64382962515,"y":30932.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"10cd9004-0088-4bc0-8fe6-b937f1bb311b","savedPayload":{"position":{"x":17865.64382962515,"y":30918.23747069523},"targetPosition":{"x":17841.64382962515,"y":30932.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4242da4b-a67e-44d8-8a19-b1c2f078c94c","savedPayload":{"position":{"x":18241.733119380056,"y":32677.766244135688},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CoinEx","config":"{ \n\"codeName\": \"coinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"af78f796-60e5-4794-87b8-772c7bc74be1","savedPayload":{"position":{"x":18043.64382962515,"y":31069.23747069523},"targetPosition":{"x":18000.64382962515,"y":31106.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d351e6d9-36eb-4d0e-aca5-94429bbb23a3","savedPayload":{"position":{"x":18094.64382962515,"y":31090.23747069523},"targetPosition":{"x":18000.64382962515,"y":31106.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"62ad0961-6bdf-4a4a-a340-610816742d0a","savedPayload":{"position":{"x":18120.179423675774,"y":32631.860008654276},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"COSS","config":"{ \n\"codeName\": \"coss\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e6315232-c6b1-4e25-aade-7bc7ba9ba6ac","savedPayload":{"position":{"x":17787.64382962515,"y":30984.23747069523},"targetPosition":{"x":17874.64382962515,"y":31049.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b1e8451f-09a2-47b0-add3-cf9c35c487bb","savedPayload":{"position":{"x":17829.64382962515,"y":31095.23747069523},"targetPosition":{"x":17874.64382962515,"y":31049.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"695029de-7f61-45bb-aa4c-c6d51e6369ed","savedPayload":{"position":{"x":18004.301618063546,"y":32573.08061122679},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CREX24","config":"{ \n\"codeName\": \"crex24\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c5e12f4a-fb26-40d3-9e70-751b55018e74","savedPayload":{"position":{"x":17910.64382962515,"y":31024.23747069523},"targetPosition":{"x":17860.64382962515,"y":31075.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"00cb629e-bad4-4c6e-8abb-499cad3992f4","savedPayload":{"position":{"x":17938.64382962515,"y":31054.23747069523},"targetPosition":{"x":17860.64382962515,"y":31075.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"07a7ec7c-273e-4675-8d8d-21ab8514a1f0","savedPayload":{"position":{"x":17895.458263866083,"y":32502.117186545547},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Deribit","config":"{ \n\"codeName\": \"deribit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f0b2354b-89e3-4eca-b051-664a3b8283f6","savedPayload":{"position":{"x":17862.64382962515,"y":30844.23747069523},"targetPosition":{"x":17906.64382962515,"y":30929.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4ae1f824-82a8-4796-a2d5-3d2358d8089f","savedPayload":{"position":{"x":17912.64382962515,"y":31024.23747069523},"targetPosition":{"x":17906.64382962515,"y":30929.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"21971815-4248-45df-8e04-20b9a5a83f06","savedPayload":{"position":{"x":17794.92544989493,"y":32419.801715882462},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"DigiFinex","config":"{ \n\"codeName\": \"digifinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e583c93e-9a44-4e0d-acb7-56d7e00a555a","savedPayload":{"position":{"x":17954.64382962515,"y":30992.23747069523},"targetPosition":{"x":17996.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8917c7c0-b420-4d4f-a35a-c0fc6870f0de","savedPayload":{"position":{"x":18052.64382962515,"y":30972.23747069523},"targetPosition":{"x":17996.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b7d56781-0c51-4ec1-95fd-bf4dc8c00352","savedPayload":{"position":{"x":17703.88183147586,"y":32327.0992728693},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"DSX","config":"{ \n\"codeName\": \"dsx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"d672ab56-cd32-4ff5-8fc5-3733262aeccb","savedPayload":{"position":{"x":17916.64382962515,"y":31106.23747069523},"targetPosition":{"x":17955.64382962515,"y":31011.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3731a7b5-ba9d-483e-bb41-abf3ae0232c6","savedPayload":{"position":{"x":17878.64382962515,"y":30946.23747069523},"targetPosition":{"x":17955.64382962515,"y":31011.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4c543abc-7372-4701-bc58-107578d45c25","savedPayload":{"position":{"x":17623.394811792878,"y":32225.09670889175},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FCoin","config":"{ \n\"codeName\": \"fcoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"a97d578c-6d7f-403c-8294-18aacf14abd8","savedPayload":{"position":{"x":17893.64382962515,"y":30953.23747069523},"targetPosition":{"x":17919.64382962515,"y":30948.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"442c3834-482e-4928-9255-8ac859ae012e","savedPayload":{"position":{"x":17905.64382962515,"y":30896.23747069523},"targetPosition":{"x":17919.64382962515,"y":30948.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6ddedcbd-07cb-4928-91b3-348f47118391","savedPayload":{"position":{"x":17554.408027561767,"y":32114.989910750606},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FCoinJP","config":"{ \n\"codeName\": \"fcoinjp\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"4a8a9810-6df6-451a-ab26-22bd7e7be85a","savedPayload":{"position":{"x":17930.64382962515,"y":31129.23747069523},"targetPosition":{"x":17942.64382962515,"y":31052.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"138ab40c-18ca-4a11-9709-0baa040873e6","savedPayload":{"position":{"x":18007.64382962515,"y":31122.23747069523},"targetPosition":{"x":17942.64382962515,"y":31052.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"982627ea-df84-4ba9-9219-612fbe1e4276","savedPayload":{"position":{"x":17497.730285752426,"y":31998.069779982467},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FTX","config":"{ \n\"codeName\": \"ftx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"20c0a4f5-bdb9-46cc-af7e-2111964551e3","savedPayload":{"position":{"x":17886.64382962515,"y":30940.23747069523},"targetPosition":{"x":17960.64382962515,"y":31019.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"75c99a0b-d3c9-4073-9283-d33e539c36bb","savedPayload":{"position":{"x":17992.64382962515,"y":31061.23747069523},"targetPosition":{"x":17960.64382962515,"y":31019.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0c0bcf5c-2774-423e-9fcf-c512b38dd06d","savedPayload":{"position":{"x":17454.026081066615,"y":31875.707098219504},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Gate.io","config":"{ \n\"codeName\": \"gateio\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"71a15089-9d40-4726-9a41-37d406064164","savedPayload":{"position":{"x":17930.64382962515,"y":30993.23747069523},"targetPosition":{"x":17880.64382962515,"y":31031.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c025e976-c2c6-49de-81ec-48e2f737b412","savedPayload":{"position":{"x":17925.64382962515,"y":31053.23747069523},"targetPosition":{"x":17880.64382962515,"y":31031.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c4028289-4cdb-4da0-90e6-5f93328b8e03","savedPayload":{"position":{"x":17423.807805345143,"y":31749.336456028108},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Gemini","config":"{ \n\"codeName\": \"gemini\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9eb15872-8d15-4086-9920-46909eb5f9e7","savedPayload":{"position":{"x":17951.64382962515,"y":30901.23747069523},"targetPosition":{"x":17971.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"a84dcf06-57c6-47d7-97a0-9f03f3af8b34","savedPayload":{"position":{"x":18045.64382962515,"y":30891.23747069523},"targetPosition":{"x":17971.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"58bf8247-baef-4ea6-a483-7ed8f0ba5043","savedPayload":{"position":{"x":17407.429740242005,"y":31620.439433646203},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"HitBTC","config":"{ \n\"codeName\": \"hitbtc\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"1632c520-fa79-442f-b33b-430cb1356de6","savedPayload":{"position":{"x":17809.64382962515,"y":31086.23747069523},"targetPosition":{"x":17880.64382962515,"y":31069.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"576d1666-dbd3-4914-9fe2-fa05bdf72eea","savedPayload":{"position":{"x":17840.64382962515,"y":31148.23747069523},"targetPosition":{"x":17880.64382962515,"y":31069.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8384fa0b-854c-4c23-846e-a5da0179a738","savedPayload":{"position":{"x":17405.083903595932,"y":31490.527230809537},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"HitBTC","config":"{ \n\"codeName\": \"hitbtc2\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9a29cb9e-ee8d-4315-8532-eef82224b84a","savedPayload":{"position":{"x":17838.64382962515,"y":30922.23747069523},"targetPosition":{"x":17829.64382962515,"y":30949.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"badd79e7-1e21-4dc3-bfa7-8dfb4a6c6267","savedPayload":{"position":{"x":17920.64382962515,"y":30944.23747069523},"targetPosition":{"x":17829.64382962515,"y":30949.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"09c634c2-5aba-49c5-80bc-4fd4175e7f0c","savedPayload":{"position":{"x":17416.79779819678,"y":31361.12294931652},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Huobi Pro","config":"{ \n\"codeName\": \"huobipro\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"86caa38c-5bdf-40e4-b27b-8d8b64319575","savedPayload":{"position":{"x":18071.64382962515,"y":31171.23747069523},"targetPosition":{"x":17996.64382962515,"y":31077.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"001225af-c715-4566-9502-f8f0ac1c4531","savedPayload":{"position":{"x":18040.64382962515,"y":31019.23747069523},"targetPosition":{"x":17996.64382962515,"y":31077.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"967c3914-a76d-4389-9c7e-9c258ae683bd","savedPayload":{"position":{"x":17442.43408934047,"y":31233.743736052187},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Huobi Russia","config":"{ \n\"codeName\": \"huobiru\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9b7b32d6-a42e-44bb-8065-5aa32b1e844b","savedPayload":{"position":{"x":17980.64382962515,"y":31034.23747069523},"targetPosition":{"x":17957.64382962515,"y":31088.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8d74201c-33cd-4e12-8920-b08d0ef97572","savedPayload":{"position":{"x":17992.64382962515,"y":31105.23747069523},"targetPosition":{"x":17957.64382962515,"y":31088.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6f97bb5c-8d85-43ee-86a1-33e22cdfbb5e","savedPayload":{"position":{"x":17481.692214952825,"y":31109.882995828142},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"KKEX","config":"{ \n\"codeName\": \"kkex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"daa4e07a-1cd8-4d92-8004-2eabfaa62f77","savedPayload":{"position":{"x":17924.64382962515,"y":31038.23747069523},"targetPosition":{"x":17987.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"cb64951f-d984-4f51-a751-166a316084f3","savedPayload":{"position":{"x":17945.64382962515,"y":31156.23747069523},"targetPosition":{"x":17987.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"16ae95ce-796f-4f2b-942c-f98dcbf9cf4b","savedPayload":{"position":{"x":17534.11190940509,"y":30990.99288257655},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Kraken","config":"{ \n\"codeName\": \"kraken\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"747af60f-c8b9-4377-aa6c-172d4137ea23","savedPayload":{"position":{"x":17854.64382962515,"y":31008.23747069523},"targetPosition":{"x":17946.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c75f7d97-9dc2-4d3e-89eb-f8a3d5f16368","savedPayload":{"position":{"x":17916.64382962515,"y":30872.23747069523},"targetPosition":{"x":17946.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"644efe9c-597a-4ddf-9e28-b33fb3b62d3e","savedPayload":{"position":{"x":17599.078599707587,"y":30878.467274173025},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"KuCoin","config":"{ \n\"codeName\": \"kucoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"01ca3037-4ed3-499e-ad6b-e14ca1d4a51f","savedPayload":{"position":{"x":17919.64382962515,"y":30949.23747069523},"targetPosition":{"x":17920.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8b3c4ce0-98b1-4d46-bd02-6cf44c3dd686","savedPayload":{"position":{"x":17998.64382962515,"y":30978.23747069523},"targetPosition":{"x":17920.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d79bc720-68e1-4771-a66a-bcffa30639d3","savedPayload":{"position":{"x":17675.830610816145,"y":30773.625430492953},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"LBank","config":"{ \n\"codeName\": \"lbank\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"def3f9d0-f09e-4e09-8b6d-a4c322a4384b","savedPayload":{"position":{"x":17877.64382962515,"y":31024.23747069523},"targetPosition":{"x":17838.64382962515,"y":31032.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"53eac3c1-96d6-4cb1-b54d-f3f174eaf733","savedPayload":{"position":{"x":17764.64382962515,"y":31036.23747069523},"targetPosition":{"x":17838.64382962515,"y":31032.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"cb2558d6-dab0-4f35-b83f-7cfc161b3d4f","savedPayload":{"position":{"x":17763.468095575536,"y":30677.69652629567},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Mercado Bitcoin","config":"{ \n\"codeName\": \"mercado\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"83ab2c39-e844-496f-bebb-7b8607428902","savedPayload":{"position":{"x":17849.64382962515,"y":31081.23747069523},"targetPosition":{"x":17849.64382962515,"y":30986.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d69e722e-c71a-462a-8bbd-d3482d0eab21","savedPayload":{"position":{"x":17771.64382962515,"y":30887.23747069523},"targetPosition":{"x":17849.64382962515,"y":30986.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5002072e-145c-4aeb-a611-3e0e4c60ee5d","savedPayload":{"position":{"x":17860.963584604677,"y":30591.805240274254},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"OKCoin","config":"{ \n\"codeName\": \"okcoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"1e4dd5c8-0545-4698-8695-c985880243a3","savedPayload":{"position":{"x":17921.64382962515,"y":31043.23747069523},"targetPosition":{"x":17967.64382962515,"y":30969.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0e188cae-9764-4963-a78b-e5d7ef272522","savedPayload":{"position":{"x":18005.64382962515,"y":30891.23747069523},"targetPosition":{"x":17967.64382962515,"y":30969.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"1f860b4b-2893-4a51-8649-19c47d494a37","savedPayload":{"position":{"x":17967.17403243568,"y":30516.958569226157},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"OKEX","config":"{ \n\"codeName\": \"okex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"7f618566-3d10-4c3c-90b2-7541a5146eeb","savedPayload":{"position":{"x":17770.64382962515,"y":31094.23747069523},"targetPosition":{"x":17847.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"21205576-5d12-452c-814f-eb56182162ae","savedPayload":{"position":{"x":17794.64382962515,"y":31173.23747069523},"targetPosition":{"x":17847.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"aa0edec0-8b27-4f94-abce-1e437ce5aba6","savedPayload":{"position":{"x":18080.854218676865,"y":30454.034021936455},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"RightBTC","config":"{ \n\"codeName\": \"rightbtc\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"ade372e9-5070-4fa9-843e-57732c4106c3","savedPayload":{"position":{"x":17999.64382962515,"y":30964.23747069523},"targetPosition":{"x":17991.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b63d440e-4501-475c-b8a6-2b9a144e32a1","savedPayload":{"position":{"x":17984.64382962515,"y":30901.23747069523},"targetPosition":{"x":17991.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c20cd9e1-52a0-4d17-b90c-e9d5b63315ce","savedPayload":{"position":{"x":18200.67134708334,"y":30403.76933118965},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"STEX","config":"{ \n\"codeName\": \"stex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f1d65161-4922-4a1e-ac98-df1a842347a7","savedPayload":{"position":{"x":17872.64382962515,"y":31001.23747069523},"targetPosition":{"x":17892.64382962515,"y":31092.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c313b2c6-6154-4a9a-b826-fd99cc500cd9","savedPayload":{"position":{"x":17888.64382962515,"y":31186.23747069523},"targetPosition":{"x":17892.64382962515,"y":31092.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0ea23137-3c65-4de1-9772-6ac1b65196e8","savedPayload":{"position":{"x":18325.220671374373,"y":30366.753804527314},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TideBit","config":"{ \n\"codeName\": \"tidebit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c92318bd-8b2d-489b-b8e8-cf30fb63286e","savedPayload":{"position":{"x":17981.64382962515,"y":31021.23747069523},"targetPosition":{"x":17978.64382962515,"y":31048.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"83bca3ec-fc1c-435c-b5fe-b1cf92463fd1","savedPayload":{"position":{"x":18051.64382962515,"y":31072.23747069523},"targetPosition":{"x":17978.64382962515,"y":31048.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5563c310-701a-4c1e-8155-87c08c927ce3","savedPayload":{"position":{"x":18453.041964599197,"y":30343.421415155935},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TimeX","config":"{ \n\"codeName\": \"timex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"5c004b5f-eec4-414f-8d01-d9b3fddeee9e","savedPayload":{"position":{"x":17892.64382962515,"y":30973.23747069523},"targetPosition":{"x":17949.64382962515,"y":30914.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"59a33add-d0e9-4ae1-8a01-f1e0ed09cb61","savedPayload":{"position":{"x":17911.64382962515,"y":30878.23747069523},"targetPosition":{"x":17949.64382962515,"y":30914.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"27d69fa7-b561-4986-8c0d-1b374e7e1bf1","savedPayload":{"position":{"x":18582.63663896287,"y":30334.045714007894},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TOP.Q","config":"{ \n\"codeName\": \"topq\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"eafef6a3-eed2-470e-a15c-aa4c10001cd2","savedPayload":{"position":{"x":17818.64382962515,"y":31115.23747069523},"targetPosition":{"x":17847.64382962515,"y":31105.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"2d5eb813-ceb6-40cd-8682-7205596bb8b5","savedPayload":{"position":{"x":17759.64382962515,"y":31188.23747069523},"targetPosition":{"x":17847.64382962515,"y":31105.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8fdf13d8-e8d2-4ef4-8b34-f492a25d753a","savedPayload":{"position":{"x":18712.485315398026,"y":30338.736622606855},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Upbit","config":"{ \n\"codeName\": \"upbit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f456fec2-cee6-4f0c-b865-1188088879c9","savedPayload":{"position":{"x":17919.64382962515,"y":30973.23747069523},"targetPosition":{"x":17991.64382962515,"y":30980.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"947c1ca0-bff9-4372-b153-40054e29b705","savedPayload":{"position":{"x":17921.64382962515,"y":31014.23747069523},"targetPosition":{"x":17991.64382962515,"y":30980.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"74e57ecd-3394-42b4-b2c4-6f216f7e41db","savedPayload":{"position":{"x":18841.065636895226,"y":30357.439144338445},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"WhiteBit","config":"{ \n\"codeName\": \"whitebit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c16eae45-a568-4b2e-b064-4431bdf34c24","savedPayload":{"position":{"x":17767.64382962515,"y":30899.23747069523},"targetPosition":{"x":17834.64382962515,"y":30950.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"dfdf793f-4ba6-4215-a325-323c0f223553","savedPayload":{"position":{"x":17920.64382962515,"y":31004.23747069523},"targetPosition":{"x":17834.64382962515,"y":30950.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"467ece1e-d1d0-4a11-ae7a-d0e22cd4eba5","savedPayload":{"position":{"x":18966.87011674703,"y":30389.934009235236},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"ZB","config":"{ \n\"codeName\": \"zb\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"db206cbd-a587-4e8e-acbe-6581ad3b5cc4","savedPayload":{"position":{"x":17855.64382962515,"y":31027.23747069523},"targetPosition":{"x":17861.64382962515,"y":30951.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"1dd658c5-7755-44b7-85f0-9bcd787762a0","savedPayload":{"position":{"x":17789.64382962515,"y":31044.23747069523},"targetPosition":{"x":17861.64382962515,"y":30951.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"07df07e8-39a8-4fbc-a0c8-150f20b6ac59","savedPayload":{"position":{"x":19088.423812451314,"y":30435.840244716648},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"51f64e29-e3ab-4683-a5de-f397fbf94260","savedPayload":{"position":{"x":18603.301618063546,"y":31534.850126685462},"targetPosition":{"x":18903.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchanges","name":"Testing Queue","project":"Superalgos","exchanges":[],"id":"895ce4b1-4890-4216-89ba-a012181d2546","savedPayload":{"position":{"x":18753.301618063546,"y":30755.427263279467},"targetPosition":{"x":18903.301618063546,"y":31015.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"signalsProviders":[],"id":"7217b56c-e854-4c06-8b8a-d5d3c05a153d","savedPayload":{"position":{"x":18917.301618063546,"y":19655.2348844148},"targetPosition":{"x":18917.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""}}},{"type":"Charting Space","name":"New Charting Space","project":"Superalgos","viewport":{"type":"Viewport","name":"New Viewport","config":"{\"zoom\":\"0.00\"}","project":"Superalgos","id":"01713f1d-91b8-44f9-9c5d-a0c12fd09037","savedPayload":{"position":{"x":22918.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"frame":{"position":{"x":245.62500000000045,"y":440.12500000000006}}}},"projectDashboards":[{"type":"Project Dashboards","name":"Superalgos","project":"Superalgos","dashboards":[{"type":"Dashboard","name":"Testing Environment My Computer","project":"Superalgos","timeMachines":[{"type":"Time Machine","name":"Example Custom Chart","config":"{}","project":"Superalgos","timeScale":{"type":"Time Scale","name":"New Time Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"fromDate\": \"2020-01-01T00:00:00.000Z\",\n \"toDate\": \"2021-01-23T23:59:59.999Z\"\n}","project":"Superalgos","id":"691e2b6e-6b13-4a94-a8cd-15bbad6e8d2b","savedPayload":{"position":{"x":21942.434665834,"y":29653.977644897117},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"rateScale":{"type":"Rate Scale","name":"New Rate Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"minValue\": 3744.3087,\n \"maxValue\": 42369.5\n}","project":"Superalgos","id":"d1c91955-e558-4ffe-a349-895405dd7475","savedPayload":{"position":{"x":21837.45195066214,"y":29705.749390696466},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrameScale":{"type":"Time Frame Scale","name":"New Time Frame Scale","config":"{\"value\":\"24-hs\"}","project":"Superalgos","id":"69064a57-bfa3-4a7a-a597-55887057befb","savedPayload":{"position":{"x":21720.64837946537,"y":29713.405101221888},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timelineCharts":[{"type":"Timeline Chart","name":"Indicators","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Candles Volumes","project":"Superalgos","layers":[{"type":"Layer","name":"Candles","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"550e7d96-2b55-4cb5-91d5-6fbceb32cbb8","savedPayload":{"position":{"x":21459.806237131383,"y":30535.58688508041},"targetPosition":{"x":21459.806237131383,"y":30235.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Candles","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab"}}}],"layerFolders":[],"id":"a9026e9d-f9c2-4509-9a75-862421b5c70b","savedPayload":{"position":{"x":21459.806237131383,"y":30235.58688508041},"targetPosition":{"x":21459.806237131383,"y":29935.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Layers","name":"Resistances and Supports","project":"Superalgos","layers":[{"type":"Layer","name":"Resistances","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"ea7115b6-1324-43dc-8fa2-90c12c2c2c48","savedPayload":{"position":{"x":21049.99861599605,"y":30345.394506215744},"targetPosition":{"x":21199.99861599605,"y":30085.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Resistances","id":"a1669770-1bbe-40f7-acb3-ded15272935f"}}},{"type":"Layer","name":"Supports","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2d16e7e1-8676-4041-a1b1-0172e023558a","savedPayload":{"position":{"x":20899.99861599605,"y":30085.58688508041},"targetPosition":{"x":21199.99861599605,"y":30085.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Supports","id":"64899503-b618-493a-ba94-bfad2051a611"}}}],"layerFolders":[],"id":"b7fed612-b218-4378-bb3f-6c90fb947449","savedPayload":{"position":{"x":21199.99861599605,"y":30085.58688508041},"targetPosition":{"x":21459.806237131383,"y":29935.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"aa6b9a8f-d5f4-4f60-b3fa-bdf957806bfb","savedPayload":{"position":{"x":21459.806237131383,"y":29935.58688508041},"targetPosition":{"x":21609.806237131383,"y":29675.779263945078},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":0,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Data Mine Products","name":"Masters","id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0"}}},"id":"6a4b0ce0-7e88-4fe3-b9b5-2116d81b2da0","savedPayload":{"position":{"x":21609.806237131383,"y":29675.779263945078},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading Engine","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Engine","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Episode","project":"Superalgos","layers":[{"type":"Layer","name":"Trading Episode Counters","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fbbb590b-c94d-4625-94e2-bc4bfa2ab6f9","savedPayload":{"position":{"x":17117.615314676776,"y":27603.533941128822},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Counters","id":"a01b42b0-ea87-47ab-b0e9-52d4b10cb631"}}},{"type":"Layer","name":"Trading Episode Statistics","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ab219d3d-1f44-4448-b5f9-f9f6ace6caea","savedPayload":{"position":{"x":17051.16747388602,"y":27764.15503654623},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Statistics","id":"559a20a7-6697-4245-9d6c-ad7c0e31ff84"}}},{"type":"Layer","name":"Episode Candle","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"7dd6f9d6-3840-4a95-a9c9-9445a1335868","savedPayload":{"position":{"x":16933.846232243683,"y":27892.241373813282},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Candle","id":"24fab05f-ff78-4cca-af61-d4d0bb2f2960"}}},{"type":"Layer","name":"Episode Balances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"371bfe04-1b2d-4d60-ae70-03a2f7522466","savedPayload":{"position":{"x":16779.824555577114,"y":27972.466666709206},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Balances","id":"7c580919-08ce-4aff-9e84-888fdf07caec"}}},{"type":"Layer","name":"Distance To Trading Event","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f1dea1ef-69f3-4b64-8586-ec43aa281cde","savedPayload":{"position":{"x":16607.980005705944,"y":27995.20904027392},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Distance To Trading Event","id":"389797d4-8456-4258-9adf-246a6ba69016"}}},{"type":"Layer","name":"Episode Base Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"eca94344-450b-4dc9-ad80-8e202b6e0517","savedPayload":{"position":{"x":16468.146686869968,"y":28016.33671006015},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Base Asset","id":"323c7b0b-42b1-4ff0-9d4b-36c2fd605caa"}}},{"type":"Layer","name":"Episode Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a4c54659-0b38-4faf-9827-47976eb9cca7","savedPayload":{"position":{"x":16286.534133073324,"y":27862.805158861436},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Quoted Asset","id":"63594fc6-3b89-4507-bca8-2d43ef618cbe"}}},{"type":"Layer","name":"Current Episode","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"e82d97df-5b25-4967-b2b4-da065c5d3ad9","savedPayload":{"position":{"x":16186.118842172375,"y":27726.349378357005},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Episode","id":"73bb3f9e-b112-4e5a-bce9-6d4bec41cc6c"}}}],"layerFolders":[],"id":"851d853d-e2d7-4138-b5fd-563f1f844f64","savedPayload":{"position":{"x":16629.455267522357,"y":27495.510435539556},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Strategy","project":"Superalgos","layers":[{"type":"Layer","name":"Current Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"dc84698a-bce4-4979-9aca-80661b054191","savedPayload":{"position":{"x":16413.05839477738,"y":27900.48601747122},"targetPosition":{"x":16372.806838862034,"y":27461.836330732353},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Strategy","id":"515f5fd6-d860-44d4-b5d6-a19acd9c5c86"}}},{"type":"Layer","name":"Last Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"d3456e5b-0438-4273-a3ce-6b1d60573c33","savedPayload":{"position":{"x":15940.04282322282,"y":27710.982017672217},"targetPosition":{"x":16372.806838862034,"y":27461.836330732353},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Strategy","id":"556e97e8-eba3-419d-869d-950cc99371da"}}}],"layerFolders":[],"id":"6ad8b449-785f-40cc-afc0-19c68b508c17","savedPayload":{"position":{"x":16372.806838862034,"y":27461.836330732353},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Current Position","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"4b8d055f-0c36-40a6-af78-5faf9b34b72c","savedPayload":{"position":{"x":16011.911411221576,"y":27821.709717793714},"targetPosition":{"x":16167.428268555628,"y":27304.34657839513},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Position","id":"d33abc39-702b-4d7a-8435-43d90e0f2c3a"}}},{"type":"Layer","name":"Last Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ac24a200-397f-4d7c-9916-581328c74f22","savedPayload":{"position":{"x":15678.683136179856,"y":27381.4342703589},"targetPosition":{"x":16167.428268555628,"y":27304.34657839513},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Position","id":"d681fd5f-64af-4f39-9f6d-a767bef7692f"}}}],"layerFolders":[],"id":"acf27818-08f1-4c0d-9cc9-30c38ba892fb","savedPayload":{"position":{"x":16167.428268555628,"y":27304.34657839513},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Open Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"b9eeeeb3-43db-4d4f-9f28-f42e947494f9","savedPayload":{"position":{"x":15829.8024827204,"y":27504.536838373795},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stage","id":"b0961496-1af9-48cd-bbeb-ac5973192e78"}}},{"type":"Layer","name":"Close Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"eda9462a-9688-42cf-ae97-b3dfd02c718c","savedPayload":{"position":{"x":15609.804663880679,"y":27268.796716857654},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stage","id":"0c9cf78d-ce6e-4318-811d-e748ca72845d"}}},{"type":"Layer","name":"Trigger Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"1481d280-6112-4d0d-8a48-3fe4e65efc9d","savedPayload":{"position":{"x":15542.751172927,"y":26994.51154740736},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stage","id":"e298787f-b7f2-4334-931e-38b9441e43f9"}}},{"type":"Layer","name":"Manage Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"2f579332-aa55-4e51-bbf4-370614838fd3","savedPayload":{"position":{"x":15731.678465146957,"y":26701.21391555524},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stage","id":"4719b69d-b23e-4037-8c0a-b641fd8ab14c"}}}],"layerFolders":[],"id":"5b4e1c43-9fb7-439f-9ca9-e600bd41718d","savedPayload":{"position":{"x":16068.487948353533,"y":27065.178022212927},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"be00b86a-5b53-4dbd-ab79-7d135115a05e","savedPayload":{"position":{"x":15729.681254722265,"y":27141.496363567436},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"90834a1b-cc7e-48a9-be5c-0e30380af4bd"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3870b052-156c-4f10-9658-3fe3df4baf10","savedPayload":{"position":{"x":15655.766921038878,"y":26926.520781829942},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"e2112d60-5fc2-4e67-befe-d4fbd6c1de77"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"5fa754c9-ffc3-499c-b566-0031b276cb73","savedPayload":{"position":{"x":15602.003963464067,"y":26726.16283946371},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"e734b6be-ba40-468c-a94f-1153dc85e00c"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"15ec260c-02f5-46e0-853b-6e751175dac7","savedPayload":{"position":{"x":15694.595933594896,"y":26519.078790508484},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"9a973229-4d9d-45af-b5aa-64906a915f6e"}}},{"type":"Layer","name":"Last Market Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"be57de60-d843-4bc8-bcb8-d8be27ceffbb","savedPayload":{"position":{"x":15860.599521408476,"y":26370.959361875106},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Market Order","id":"56517fe9-64da-4404-83f3-005106bc1c0a"}}},{"type":"Layer","name":"Last Limit Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"407c7816-701b-43bf-92d8-cc728af78f0e","savedPayload":{"position":{"x":16074.514663407172,"y":26309.4257023683},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Limit Order","id":"d00c76e7-4be0-4518-9892-a0f6df943951"}}}],"layerFolders":[],"id":"ac1ed18a-243b-4211-bb24-83bbfc20cd0a","savedPayload":{"position":{"x":16102.435022890473,"y":26808.60560739891},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"41428787-ca89-4ab9-a5cc-29e66e7c486d","savedPayload":{"position":{"x":16563.94253388532,"y":27000.12691029475},"targetPosition":{"x":16959.887378913278,"y":26696.345955873618},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"153096ea-a48c-4ed5-9f8e-49eafa7a779c","savedPayload":{"position":{"x":16959.887378913278,"y":26696.345955873618},"targetPosition":{"x":17356.087169245202,"y":26392.358194020195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"918bdf6d-3cfe-4c8b-894d-320cc72aef70","savedPayload":{"position":{"x":17356.087169245202,"y":26392.358194020195},"targetPosition":{"x":17752.58716757543,"y":26088.09403049708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":150,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"f0cc2b79-bae6-4441-a456-9fda5962a74f","savedPayload":{"position":{"x":21521.80023504401,"y":29598.600071512363},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading System","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading System","project":"Superalgos","layers":[{"type":"Layer","name":"Trading System Errors","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"49761e84-d6c2-4c25-9604-fb2ddf93e510","savedPayload":{"position":{"x":16656.868785422477,"y":26432.858992462687},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Errors","id":"a0c29c57-0a20-4084-9697-142300f62f9c"}}},{"type":"Layer","name":"Trading System Highlights","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"622a88bb-151c-48ef-bb99-e093498bf002","savedPayload":{"position":{"x":16532.079378960796,"y":26407.941535439437},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Highlights","id":"aa0fe882-89a8-4811-8988-c589554afe9d"}}},{"type":"Layer","name":"Trading System Values","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fba6a9fb-5e9a-46dd-aa2b-33950f0ec9f1","savedPayload":{"position":{"x":16422.17772780151,"y":26345.322337891994},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Values","id":"bbc65054-b22b-4cbb-816b-529672e2f498"}}},{"type":"Layer","name":"Trading System Status","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4ec0d56a-b497-4d90-9157-094c08930962","savedPayload":{"position":{"x":16337.350686782229,"y":26251.937657405022},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Status","id":"776a3ece-8255-4e80-b60f-85bb818b561f"}}},{"type":"Layer","name":"Trading System Progress","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5db72b24-ad72-49dd-8a32-1256fb25d04a","savedPayload":{"position":{"x":16285.989038785094,"y":26136.930218774854},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Progress","id":"7593aaf9-0505-4b58-9920-235340ff2d2f"}}},{"type":"Layer","name":"Trading System Running","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"cbdfc3db-d5dd-476c-bf02-cf86d8a01300","savedPayload":{"position":{"x":16272.745363533515,"y":26011.773677977748},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Running","id":"3e2e6105-f41f-42e2-bce5-74ebb3b81cbd"}}},{"type":"Layer","name":"Trading System Announcements","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"105a157c-b33a-40d0-9711-19526b04bfda","savedPayload":{"position":{"x":16299.015550574797,"y":25888.784732962406},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Announcements","id":"faab4399-898b-4393-8c27-fa2f3109c60a"}}},{"type":"Layer","name":"Trading System Warnings","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ab8b1fdc-4319-4b37-ae29-333912412215","savedPayload":{"position":{"x":16361.786293229427,"y":25778.482294029163},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Warnings","id":"9ff0f035-ca7f-4e65-a82c-186fa7f09157"}}},{"type":"Layer","name":"Trading System Infos","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"051bd185-3255-41a5-bf62-ea8b27b32ddf","savedPayload":{"position":{"x":16480.783502595135,"y":25721.83855865352},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Infos","id":"04210a59-070a-45f1-a2a0-cf50bd4879f7"}}}],"layerFolders":[],"id":"838dab4e-c0bf-47f3-ac6a-8f815e5e666b","savedPayload":{"position":{"x":16674.50340983706,"y":26032.473650601696},"targetPosition":{"x":17060.504725681127,"y":25928.810868229375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"74e5c728-fd06-4e79-8ec1-32ab2720adf5","savedPayload":{"position":{"x":17060.504725681127,"y":25928.810868229375},"targetPosition":{"x":17476.621526107163,"y":25817.204586634994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8a7bce21-b09a-41e3-b9af-87f1939e9136","savedPayload":{"position":{"x":17183.249075924137,"y":26042.417976975546},"targetPosition":{"x":17666.14324924388,"y":25913.066804430764},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":300,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"a514d9bb-8862-4c81-b82e-dbde66abeb77","savedPayload":{"position":{"x":21470.02848924466,"y":29493.617356340503},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Objects","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Objects","project":"Superalgos","layers":[{"type":"Layer","name":"Episodes","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"17c8f568-4716-4a19-a607-689b78a83ef9","savedPayload":{"position":{"x":15863.39648009967,"y":25920.19809968253},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episodes","id":"73dff61a-7b05-4ca6-b963-99d6c578e9ba"}}},{"type":"Layer","name":"Strategies","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"86978570-76c1-4780-a91d-4e72e88ef817","savedPayload":{"position":{"x":15705.823183600161,"y":25714.050844388883},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Strategies","id":"a9c454c8-9075-4dcf-bfe9-ebd0c1658049"}}}],"layerFolders":[{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"653e6b00-bda3-4662-a2bd-934212e884d1","savedPayload":{"position":{"x":15327.86442305616,"y":25820.329298596927},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"cad1eecc-e897-4086-b42c-fcfd843c04cc"}}},{"type":"Layer","name":"Market Sell Orders","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2887f930-5d79-42ff-ab1d-7d5cdc6b47da","savedPayload":{"position":{"x":15180.506269267476,"y":25548.319695716105},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"fdf22e85-7071-4847-bdba-e3fb43a616ed"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"3040a2f6-0b1c-4ed3-a816-39c916465c9a","savedPayload":{"position":{"x":15221.387997903394,"y":25243.251366030032},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"d2b1ab31-d8a1-422b-a717-33ee7df9b07b"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"a59ef70f-534f-410b-99ef-3a700d2ca82a","savedPayload":{"position":{"x":15398.72702979423,"y":25036.45705462772},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"3b5a12db-b969-4400-8b9d-afb9b7b81642"}}}],"layerFolders":[],"id":"334a2964-17df-4237-a302-962416655896","savedPayload":{"position":{"x":15672.454225865862,"y":25457.66729056814},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Trigger Stages","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"a6b1a2c5-ca70-42b9-932f-2ff00aff2524","savedPayload":{"position":{"x":15292.017678857432,"y":25360.154463716302},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stages","id":"9fc29be1-9393-4933-95d3-bebddd73c05e"}}},{"type":"Layer","name":"Open Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"663ddaf7-784f-4baa-8f69-3ed0ef5cd685","savedPayload":{"position":{"x":15298.823311983959,"y":25050.998457959326},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stages","id":"b555388f-db93-4db1-91be-7772550afa70"}}},{"type":"Layer","name":"Manage Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"9a4be770-082c-4d0f-a747-0b74d792e76f","savedPayload":{"position":{"x":15476.277795953174,"y":24812.240105588095},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stages","id":"41953904-e48c-4176-bf0f-09d133bc444c"}}},{"type":"Layer","name":"Close Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"efb9d388-a679-49b2-b792-1b8258a489d6","savedPayload":{"position":{"x":15784.125039599678,"y":24724.90131904347},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stages","id":"47b4553c-7f2e-438c-9f4b-9ba30e943a6c"}}}],"layerFolders":[],"id":"eea75e9a-a735-4db8-9eea-cf2c4e4119e3","savedPayload":{"position":{"x":15771.52653783795,"y":25218.00065188687},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Positions","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb0ea641-23a7-48d0-a70d-f3314722f129","savedPayload":{"position":{"x":15517.085211279895,"y":24978.036206455075},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Positions","id":"6e49b57f-8c94-410f-985b-82c126155b11"}}},{"type":"Layer","name":"Position Base Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"fa1cf76f-30a6-4cfd-ba4f-8511afca64b8","savedPayload":{"position":{"x":15592.85911518537,"y":24750.27204370447},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Base Asset","id":"ae8fa9a5-95b6-4769-8ade-f9854e6855ba"}}},{"type":"Layer","name":"Position Quoted Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"bf7d5c92-8894-4040-8d2f-3f5cdec443af","savedPayload":{"position":{"x":15786.287615627753,"y":24593.84817912013},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Quoted Asset","id":"9e9b19ee-9c51-4586-b74d-d2880f13f71f"}}},{"type":"Layer","name":"Stop Loss","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"125c9155-a747-4ac4-9d9f-1b93a4ae8d17","savedPayload":{"position":{"x":16042.541437710524,"y":24564.41238111062},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Stop Loss","id":"01491591-0462-453c-91e0-6da6f554a729"}}},{"type":"Layer","name":"Take Profit","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"3745d5cd-a2be-43ed-b5df-d05c328f8665","savedPayload":{"position":{"x":16280.917386265202,"y":24663.928419862754},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Take Profit","id":"719dd8a6-58ab-41c6-9693-9b67c12232d2"}}}],"layerFolders":[],"id":"9854e8b2-d863-42f3-afd5-416d5e2c548e","savedPayload":{"position":{"x":15977.296572394282,"y":25060.75923245295},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"6e31ae33-68d1-4dca-8b29-6e59a2a4448e","savedPayload":{"position":{"x":16168.303357177294,"y":25522.64736240649},"targetPosition":{"x":16663.0166511096,"y":25588.08600416838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8c851b59-3105-460c-bb4b-cb4944db1049","savedPayload":{"position":{"x":16663.0166511096,"y":25588.08600416838},"targetPosition":{"x":17157.9116821377,"y":25653.201834587282},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"be53f7bc-6c26-4fd7-a0d0-96b965bbf655","savedPayload":{"position":{"x":17157.9116821377,"y":25653.201834587282},"targetPosition":{"x":17653.521538239824,"y":25718.280363218284},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":450,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"43eeb152-b0b8-468d-84d1-7d03fd636387","savedPayload":{"position":{"x":21462.37277871924,"y":29376.81378514373},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"499eac86-6c40-4362-a36a-5f2002081866","savedPayload":{"position":{"x":22018.806237131383,"y":29379.971642809745},"targetPosition":{"x":22168.806237131383,"y":29120.164021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":585,"y":-155},"width":240,"height":111.125,"radius":0},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}}],"id":"885265c2-ebb1-4283-a617-34a88780276d","savedPayload":{"position":{"x":22168.806237131383,"y":29120.164021674413},"targetPosition":{"x":22318.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Testing Environment","name":"New Testing Environment","id":"5882d8a8-345b-4188-b1c1-797e9ff805d9"}}},{"type":"Dashboard","name":"Production Environment My Computer","project":"Superalgos","timeMachines":[{"type":"Time Machine","name":"Lightning Strike Live Trading Session My Computer","config":"{}","project":"Superalgos","timeScale":{"type":"Time Scale","name":"New Time Scale","config":"{\n \"autoMinScale\": false,\n \"autoMaxScale\": false,\n \"fromDate\": \"2020-10-06T17:09:32.085Z\",\n \"toDate\": \"2020-10-06T21:09:32.085Z\"\n}","project":"Superalgos","id":"708c5a9f-a995-4210-aaaf-0794782f0e9e","savedPayload":{"position":{"x":21721.37277871924,"y":28379.89901593443},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"rateScale":{"type":"Rate Scale","name":"New Rate Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"minValue\": 10419.75,\n \"maxValue\": 10844.37\n}","project":"Superalgos","id":"ee3f6af0-8649-489b-9168-b4f16d2f5a78","savedPayload":{"position":{"x":21729.02848924466,"y":28263.095444737657},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrameScale":{"type":"Time Frame Scale","name":"New Time Frame Scale","config":"{\n \"value\": \"01-min\",\n \"autoMinScale\": false,\n \"autoMaxScale\": true,\n \"fromDate\": \"2020-10-05T09:53:58.939Z\",\n \"toDate\": \"2020-10-05T13:53:58.939Z\"\n}","project":"Superalgos","id":"480f9696-76df-4026-a435-7bf364c08056","savedPayload":{"position":{"x":21780.80023504401,"y":28158.112729565797},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timelineCharts":[{"type":"Timeline Chart","name":"New Data Mine Products","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Candles Volumes","project":"Superalgos","layers":[{"type":"Layer","name":"Candles","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"e3cbbcbe-c938-4669-b670-c317476e0a3b","savedPayload":{"position":{"x":16992.282280946285,"y":23856.49271176323},"targetPosition":{"x":17392.615945713467,"y":23857.108132968406},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Candles","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab"}}},{"type":"Layer","name":"Volumes","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"385a5f98-118a-43fd-b019-54e825d1f4ae","savedPayload":{"position":{"x":17192.242023030805,"y":23510.135246216414},"targetPosition":{"x":17392.615945713467,"y":23857.108132968406},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Volumes","id":"07c11481-7dbd-477d-8bf7-79212542a6aa"}}}],"layerFolders":[],"id":"6848a114-9979-41dd-8d95-3a899679ba08","savedPayload":{"position":{"x":17392.615945713467,"y":23857.108132968406},"targetPosition":{"x":17738.764681458488,"y":24056.665358937673},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Layers","name":"Resistances and Supports","project":"Superalgos","layers":[{"type":"Layer","name":"Resistances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"0cf13cfa-2a37-4691-902c-513ab5780da8","savedPayload":{"position":{"x":17538.760168957182,"y":23310.0159698544},"targetPosition":{"x":17738.97910230742,"y":23657.072015580987},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Resistances","id":"a1669770-1bbe-40f7-acb3-ded15272935f"}}},{"type":"Layer","name":"Supports","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"d9245f0b-54e8-44b1-94bd-56c7048eb5c1","savedPayload":{"position":{"x":17938.505496583897,"y":23310.043709247824},"targetPosition":{"x":17738.97910230742,"y":23657.072015580987},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Supports","id":"64899503-b618-493a-ba94-bfad2051a611"}}}],"layerFolders":[],"id":"20bd60bb-917b-4a0f-acc5-b019d1c3bd81","savedPayload":{"position":{"x":17738.97910230742,"y":23657.072015580987},"targetPosition":{"x":17738.764681458488,"y":24056.665358937673},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"4cbbc012-c91e-4acd-a8d2-feb149e728a0","savedPayload":{"position":{"x":17738.764681458488,"y":24056.665358937673},"targetPosition":{"x":17963.331767523672,"y":24445.732145877373},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":0,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Data Mine Products","name":"Masters","id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0"}}},"id":"bb7afb85-32ea-4471-8400-615a34fc126f","savedPayload":{"position":{"x":21868.806237131383,"y":28080.93353713308},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading Engine","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Engine","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Episode","project":"Superalgos","layers":[{"type":"Layer","name":"Trading Episode Counters","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"05da2270-0016-4d22-89d8-b77cd14008a9","savedPayload":{"position":{"x":12224.806237131383,"y":25700.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Counters","id":"dc6cc4ef-4bd7-4837-8442-919462314db3"}}},{"type":"Layer","name":"Trading Episode Statistics","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a4165460-e0a7-4a0d-b506-15e756dfac93","savedPayload":{"position":{"x":12219.806237131383,"y":25689.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Statistics","id":"776ed571-8321-47aa-8cfb-c8ebf565dace"}}},{"type":"Layer","name":"Episode Candle","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"371e0cd7-af57-4469-836d-45c4e6059760","savedPayload":{"position":{"x":12317.806237131383,"y":25717.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Candle","id":"ded93703-a48d-44be-9703-878c28f949cd"}}},{"type":"Layer","name":"Episode Balances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5ed81442-77cc-4101-b1ff-8c7cbac57d4f","savedPayload":{"position":{"x":12245.806237131383,"y":25698.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Balances","id":"e702f1dd-1c91-4d05-ac55-19db363f5f3a"}}},{"type":"Layer","name":"Distance To Trading Event","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5e046a6a-4f38-4b44-bae1-1aed6d4d3753","savedPayload":{"position":{"x":12313.806237131383,"y":25819.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Distance To Trading Event","id":"b8abea53-8221-47bd-91a2-cdcdd2ad1027"}}},{"type":"Layer","name":"Episode Base Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"b78a78ec-dca3-499b-881a-d2e3a82bf116","savedPayload":{"position":{"x":12330.806237131383,"y":25734.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Base Asset","id":"18bcbd26-c237-4acb-96f4-d9c95d833a42"}}},{"type":"Layer","name":"Episode Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb95c2a9-6f82-4a2a-9105-17b8f6c3c51a","savedPayload":{"position":{"x":12364.806237131383,"y":25720.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Quoted Asset","id":"c444f4b5-fa67-4c21-afa8-1f998da7a2a2"}}},{"type":"Layer","name":"Current Episode","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4ad5b6f0-f4a9-4aab-aedf-9175647498b0","savedPayload":{"position":{"x":12321.806237131383,"y":25708.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Episode","id":"057570bd-69d4-4f3c-b0d4-94ee32f61e65"}}}],"layerFolders":[],"id":"7216b7a3-1371-4f07-a395-74c547579ab4","savedPayload":{"position":{"x":12315.806237131383,"y":25752.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Strategy","project":"Superalgos","layers":[{"type":"Layer","name":"Current Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"d2c0a1c8-70ef-4f7b-835a-a99ac6a5837a","savedPayload":{"position":{"x":12210.806237131383,"y":25770.664021674413},"targetPosition":{"x":12305.806237131383,"y":25783.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Strategy","id":"88dd680c-a81b-48ae-96ba-838281abfa35"}}},{"type":"Layer","name":"Last Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"076af680-2114-480b-a979-f7eea4966d7b","savedPayload":{"position":{"x":12302.806237131383,"y":25739.664021674413},"targetPosition":{"x":12305.806237131383,"y":25783.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Strategy","id":"24af3ffc-6a52-4ee3-a30b-f068aa5b2062"}}}],"layerFolders":[],"id":"56112c60-50dd-4d19-89aa-1d46005f194f","savedPayload":{"position":{"x":12305.806237131383,"y":25783.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Current Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb93ebef-f7ee-42c2-93b8-fe46eba0874a","savedPayload":{"position":{"x":12424.806237131383,"y":25721.664021674413},"targetPosition":{"x":12427.806237131383,"y":25692.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Position","id":"25280962-e4e5-40df-9e42-9edfbad6f6d3"}}},{"type":"Layer","name":"Last Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"595e7228-5676-4f5c-82bf-baa43e9325ab","savedPayload":{"position":{"x":12488.806237131383,"y":25680.664021674413},"targetPosition":{"x":12427.806237131383,"y":25692.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Position","id":"7a95a249-132d-4e0f-9182-cc7af45cacea"}}}],"layerFolders":[],"id":"9f594c8a-87fe-4c4b-b550-493405fe0b2d","savedPayload":{"position":{"x":12427.806237131383,"y":25692.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Open Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3ce44f39-8ac9-4984-ad9d-daa53ed3f707","savedPayload":{"position":{"x":12377.806237131383,"y":25588.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stage","id":"c9c4bca7-f918-4aa8-b538-ffe8aa31d5c2"}}},{"type":"Layer","name":"Close Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a7d5f0aa-8259-4271-aa95-7b351aa9b9c0","savedPayload":{"position":{"x":12337.806237131383,"y":25588.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stage","id":"4201d7c0-43aa-4ac0-bd7e-ab26b688aa2d"}}},{"type":"Layer","name":"Trigger Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"9a9f6580-ab06-4005-9274-98f7e9a491e5","savedPayload":{"position":{"x":12387.806237131383,"y":25625.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stage","id":"4fe24ddc-973f-4a5d-bf8a-d77090486125"}}},{"type":"Layer","name":"Manage Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f60905ad-b491-45ee-9768-8087df9aef78","savedPayload":{"position":{"x":12466.806237131383,"y":25757.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stage","id":"e2f3d69e-2f0a-4463-8e74-4f0768c4fb70"}}}],"layerFolders":[],"id":"5389c77c-63a7-4495-9cc5-cdc0c70b76e6","savedPayload":{"position":{"x":12422.806237131383,"y":25658.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f602d8ef-b6a6-423f-a772-9a4b5d5b9c43","savedPayload":{"position":{"x":12422.806237131383,"y":25747.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"0e0b284a-5014-4ab0-ada0-4322c14a099e"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"0a0dd259-5704-46de-900f-5d1dc24af4f6","savedPayload":{"position":{"x":12488.806237131383,"y":25650.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"95b3db7a-9b62-4eab-a76b-4af8794da5a6"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"de6f83f6-a6d9-45c7-93fd-e2c72238040e","savedPayload":{"position":{"x":12410.806237131383,"y":25733.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"1c6eed42-23aa-4174-aade-be29222acb8c"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ac0f1c2a-5eed-45ee-84da-3d24e455abd3","savedPayload":{"position":{"x":12379.806237131383,"y":25663.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"a2f44cd5-090d-42e5-9eb7-73e732310e85"}}},{"type":"Layer","name":"Last Market Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"89def699-c33f-4344-a045-babca1f545ee","savedPayload":{"position":{"x":12478.806237131383,"y":25752.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Market Order","id":"8c24d559-ba52-46fe-81b4-8a6bf50c74b6"}}},{"type":"Layer","name":"Last Limit Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a7e04514-bf32-4021-822c-47af56c55a76","savedPayload":{"position":{"x":12504.806237131383,"y":25780.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Limit Order","id":"c451c035-5ece-451f-836f-b5334cb3f967"}}}],"layerFolders":[],"id":"a302255a-cf35-4801-ae3c-95cb47ae9613","savedPayload":{"position":{"x":12437.806237131383,"y":25742.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1857004e-2f12-4287-8847-173043d8d2ab","savedPayload":{"position":{"x":12363.806237131383,"y":25731.664021674413},"targetPosition":{"x":12380.806237131383,"y":25686.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"23ad1663-d4da-4ece-8964-30012894ae5b","savedPayload":{"position":{"x":12380.806237131383,"y":25686.664021674413},"targetPosition":{"x":12448.806237131383,"y":25597.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ddb3fafa-58f4-46c1-9b24-61efe3ec13a6","savedPayload":{"position":{"x":12448.806237131383,"y":25597.664021674413},"targetPosition":{"x":12446.806237131383,"y":25637.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":150,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"788a0207-20ea-411c-862d-b1b13db4e09f","savedPayload":{"position":{"x":21979.64837946537,"y":28043.307699856272},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading System","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading System","project":"Superalgos","layers":[{"type":"Layer","name":"Trading System Errors","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"2a1db97f-553d-47ea-b452-c90ba9af9e79","savedPayload":{"position":{"x":12242.806237131383,"y":25582.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Errors","id":"ba606f99-2ae5-44dc-b7db-399e657830e1"}}},{"type":"Layer","name":"Trading System Highlights","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3c1c9d45-c482-4374-92ad-c3c28bfb7679","savedPayload":{"position":{"x":12270.806237131383,"y":25723.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Highlights","id":"2d20d8ae-4afa-4e92-8de2-89e66e5efdee"}}},{"type":"Layer","name":"Trading System Values","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a560c8af-91cd-4aea-ab9f-01ed60892abb","savedPayload":{"position":{"x":12340.806237131383,"y":25546.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Values","id":"f8a6219c-c7b4-410a-8aa4-1910583f51c8"}}},{"type":"Layer","name":"Trading System Status","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"40debb84-1e2e-452b-99ff-95ff3994fb29","savedPayload":{"position":{"x":12322.806237131383,"y":25605.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Status","id":"dcff6f56-7646-4505-aa93-6682a110f3f2"}}},{"type":"Layer","name":"Trading System Progress","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5785c4fb-879d-4b89-aab8-9ec37d5f561b","savedPayload":{"position":{"x":12240.806237131383,"y":25559.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Progress","id":"0a9dff80-e462-4110-b988-11ce57bbbcd5"}}},{"type":"Layer","name":"Trading System Running","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"74d8c1f7-8dd5-4e2c-b3cf-7f7bcfe7143c","savedPayload":{"position":{"x":12342.806237131383,"y":25543.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Running","id":"c7e05ad0-7d4a-4ffb-9aee-191511f85ee7"}}},{"type":"Layer","name":"Trading System Announcements","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4476fcb1-3898-440f-b69e-afba06be912a","savedPayload":{"position":{"x":12402.806237131383,"y":25585.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Announcements","id":"e4811789-fd94-49b0-9917-8d9d434f997d"}}},{"type":"Layer","name":"Trading System Warnings","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"43fe3418-9b3c-4cd9-b9a9-3994851e0b65","savedPayload":{"position":{"x":12310.806237131383,"y":25555.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Warnings","id":"029ff3a7-9c65-425f-855a-882df68fa05b"}}},{"type":"Layer","name":"Trading System Infos","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"de34ba07-61b5-4785-bcf5-ff5b81d63e48","savedPayload":{"position":{"x":12227.806237131383,"y":25559.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Infos","id":"0f47adaf-25a0-431f-b15b-0fbf44069b38"}}}],"layerFolders":[],"id":"36e02794-0943-4520-af39-2f274050610c","savedPayload":{"position":{"x":12310.806237131383,"y":25627.664021674413},"targetPosition":{"x":12365.806237131383,"y":25585.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1ccfa34c-ca21-4ac3-be74-30f85549bf5e","savedPayload":{"position":{"x":12365.806237131383,"y":25585.664021674413},"targetPosition":{"x":12339.806237131383,"y":25637.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c1c4bd7c-b755-461a-a5ed-b59804b4c280","savedPayload":{"position":{"x":12339.806237131383,"y":25637.664021674413},"targetPosition":{"x":12377.806237131383,"y":25540.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":300,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"ed6507e7-437f-4740-a897-11dc4da4d20a","savedPayload":{"position":{"x":22096.45195066214,"y":28050.963410381693},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Objects","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Objects","project":"Superalgos","layers":[{"type":"Layer","name":"Episodes","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"76852fcc-d524-43b8-a0b1-8645c2fed91e","savedPayload":{"position":{"x":12710.806237131383,"y":25614.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episodes","id":"c6fd6067-4b57-4860-ae3b-5668e4444490"}}},{"type":"Layer","name":"Strategies","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"43b43957-23d5-401b-b3e0-391c430b72c9","savedPayload":{"position":{"x":12705.806237131383,"y":25579.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Strategies","id":"60f88096-7343-42d1-afad-83fecd22fb44"}}}],"layerFolders":[{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"aaff7fb6-bd83-48f2-819a-a1dd674876a7","savedPayload":{"position":{"x":12579.806237131383,"y":25470.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"9f939086-c934-4924-8353-776707a7cf10"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bec241f4-5a8f-4fe7-9620-76d92f64da9c","savedPayload":{"position":{"x":12705.806237131383,"y":25579.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"da5f279e-d387-43cf-80f4-fc114b9ac906"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2d03d083-7199-4bf2-8e8a-4c96f23a16a8","savedPayload":{"position":{"x":12735.806237131383,"y":25521.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"367646bb-839a-4071-8305-6d26a647585d"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"cb5de20d-e440-4bdb-a074-c408740e9022","savedPayload":{"position":{"x":12631.806237131383,"y":25476.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"0b2fc73a-9635-40b2-98d8-0c79c69175a9"}}}],"layerFolders":[],"id":"a8409c29-905d-495f-bbca-3d0eef14f91c","savedPayload":{"position":{"x":12649.806237131383,"y":25488.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Trigger Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"04d1a0a8-1419-4fbd-9c28-eef6cfefd5d4","savedPayload":{"position":{"x":12584.806237131383,"y":25552.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stages","id":"7fe8c58f-9cad-47c9-ba4e-d66bff094dcf"}}},{"type":"Layer","name":"Open Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"74cda6e5-4fe2-41ef-a611-2c0374780ad5","savedPayload":{"position":{"x":12663.806237131383,"y":25503.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stages","id":"41f17745-1819-4681-8a2b-9bdda3cd67c4"}}},{"type":"Layer","name":"Manage Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fb041378-9424-4709-a9ed-79426fcdfe68","savedPayload":{"position":{"x":12721.806237131383,"y":25661.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stages","id":"e89c8bfd-fac9-4aff-afc0-3a89c1dc2710"}}},{"type":"Layer","name":"Close Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"6c4ac373-c5ff-4bfd-8047-4caaba6b7788","savedPayload":{"position":{"x":12659.806237131383,"y":25585.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stages","id":"bc2c6503-e935-4ad7-a76a-89b062d41e91"}}}],"layerFolders":[],"id":"4b2ee5fd-d4f7-4a7c-bb6e-5e4c633b1b9f","savedPayload":{"position":{"x":12680.806237131383,"y":25593.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Positions","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"4f77d851-9e93-4e85-9cfb-ec2ab200d79b","savedPayload":{"position":{"x":12581.806237131383,"y":25650.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Positions","id":"3ed594a0-8452-4bd8-9eaa-37cd83a45b90"}}},{"type":"Layer","name":"Position Base Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"0213c668-a6d8-4737-ae57-d59d62b8f715","savedPayload":{"position":{"x":12767.806237131383,"y":25594.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Base Asset","id":"88997c97-e77f-490e-9eb5-c7531beec132"}}},{"type":"Layer","name":"Position Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f07986eb-010f-46cd-803d-dcac674adb80","savedPayload":{"position":{"x":12745.806237131383,"y":25673.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Quoted Asset","id":"b4772611-d5d0-4fbd-b689-d42de3c045d4"}}},{"type":"Layer","name":"Stop Loss","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"3f8f8fa3-2149-42d6-92e9-214354cfa186","savedPayload":{"position":{"x":12630.806237131383,"y":25581.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Stop Loss","id":"9b064960-3829-441f-b955-334fb8324a53"}}},{"type":"Layer","name":"Take Profit","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"65ec58e6-2c00-41d4-a145-e6b7e7178bf0","savedPayload":{"position":{"x":12743.806237131383,"y":25590.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Take Profit","id":"cbcc817b-4333-4c80-addc-e2a0ee0845c1"}}}],"layerFolders":[],"id":"66e5c011-9163-422d-863f-115135f832ad","savedPayload":{"position":{"x":12672.806237131383,"y":25618.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"91b8a8e8-823d-4746-967f-c8d85a1ad3ad","savedPayload":{"position":{"x":12687.806237131383,"y":25530.664021674413},"targetPosition":{"x":12591.806237131383,"y":25565.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"dcaccce7-d98d-49b3-b3b6-e83495b688c3","savedPayload":{"position":{"x":12591.806237131383,"y":25565.664021674413},"targetPosition":{"x":12523.806237131383,"y":25633.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e328f755-80a6-4799-8f12-002a2ddb983d","savedPayload":{"position":{"x":12523.806237131383,"y":25633.664021674413},"targetPosition":{"x":12489.806237131383,"y":25562.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":450,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"93708a53-ad8d-48e0-9728-b87ea96d1545","savedPayload":{"position":{"x":22201.434665834,"y":28102.735156181043},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"cc1fcc1e-81de-4011-8e59-c37ebe32ecf7","savedPayload":{"position":{"x":22018.806237131383,"y":28340.741158268414},"targetPosition":{"x":22168.806237131383,"y":28600.548779403747},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":585,"y":65},"width":240,"height":113.625,"radius":0},"referenceParent":{"type":"Live Trading Session","name":"Lightning Strike","id":"1ce123af-467f-4295-b317-dba8729faf25"}}}],"id":"abc16155-6614-4397-bf7e-ab4a0ff7c1a4","savedPayload":{"position":{"x":22168.806237131383,"y":28600.548779403747},"targetPosition":{"x":22318.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Production Environment","name":"New Production Environment","id":"65a40d20-837c-4652-8356-f8054b4e1346"}}}],"id":"84a1b1ba-4888-4eac-8762-7084f0ee5de7","savedPayload":{"position":{"x":22318.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"21d2ec55-9e56-4652-8e96-c7e451262c36","savedPayload":{"position":{"x":22618.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"c"}}},{"type":"Plugins","name":"New Plugins","project":"Superalgos","pluginProjects":[{"type":"Plugin Project","name":"Superalgos","config":"{ \n \"codeName\": \"Superalgos\"\n}","project":"Superalgos","pluginDataMines":{"type":"Plugin Data Mines","name":"New Plugin Data Mines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters","project":"Superalgos","id":"d5234bd2-ef4e-4856-a6a0-ce7659653a48","savedPayload":{"position":{"x":14648.352187356151,"y":28990.05301821844},"targetPosition":{"x":14635.871225686036,"y":10349.288271084537},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ecc1a524-de9b-4e73-8874-b99a7ea0402b","savedPayload":{"position":{"x":14635.871225686036,"y":10349.288271084537},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plugin File","name":"Alpha","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Alpha","project":"Superalgos","id":"9d9d6275-91e1-448d-b162-8069adf7f207","savedPayload":{"position":{"x":14658.262986317583,"y":19632.85151122931},"targetPosition":{"x":14810.468084630062,"y":10200.168466117855},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5b8a1d1e-59db-484c-8dfe-7d35f2aa8770","savedPayload":{"position":{"x":14810.468084630062,"y":10200.168466117855},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plugin File","name":"Sparta","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Sparta","project":"Superalgos","id":"449f1832-f5b8-4e7e-a010-d892d721d3bc","savedPayload":{"position":{"x":14665.067482786275,"y":37715.63150649338},"targetPosition":{"x":15039.37033286441,"y":10218.18346374989},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0486ca8b-855a-4295-ba63-6f63421b4a13","savedPayload":{"position":{"x":15039.37033286441,"y":10218.18346374989},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"cbc3d9be-5e59-45d8-bb0f-4ec82763691d","savedPayload":{"position":{"x":14903.173182942546,"y":10485.4854210064},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingMines":{"type":"Plugin Trading Mines","name":"New Plugin Trading Mines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters","project":"Superalgos","id":"ad1ce785-858f-4cfc-ba68-108b5e0c54d9","savedPayload":{"position":{"x":31037.217404066585,"y":10729.643045797242},"targetPosition":{"x":15481.28847788,"y":10418.13122451946},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8a64c00e-4f8c-49bf-b57d-4e2e388bae41","savedPayload":{"position":{"x":15481.28847788,"y":10418.13122451946},"targetPosition":{"x":15238.583379567515,"y":10594.466800207203},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8d881813-3ab9-4e8b-ab5a-48dedab2dd19","savedPayload":{"position":{"x":15238.583379567515,"y":10594.466800207203},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingSystems":{"type":"Plugin Trading Systems","name":"New Plugin Trading Systems","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters-Lightning-Strike","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters-Lightning-Strike","project":"Superalgos","id":"37ab4b0d-6bd8-46b6-9778-e193c32669a4","savedPayload":{"position":{"x":24926.365708673427,"y":19688.576468868458},"targetPosition":{"x":15481.28847788,"y":11123.473527270431},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5fdcecee-8c8f-4e0f-b36b-81e9231970a6","savedPayload":{"position":{"x":15481.28847788,"y":11123.473527270431},"targetPosition":{"x":15238.583379567515,"y":10947.137951582688},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3569d452-c593-4e54-a356-7ff8c6b519f3","savedPayload":{"position":{"x":15238.583379567515,"y":10947.137951582688},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingEngines":{"type":"Plugin Trading Engines","name":"New Plugin Trading Engines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Low-Frequency","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Low-Frequency","project":"Superalgos","id":"e117a2a4-09b3-4181-8455-e680de3bdeb3","savedPayload":{"position":{"x":31033.55093774257,"y":19568.049392142086},"targetPosition":{"x":14810.468084630062,"y":11341.436285672036},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e9270d67-4630-4ac9-91ca-1dec4fb5aa38","savedPayload":{"position":{"x":14810.468084630062,"y":11341.436285672036},"targetPosition":{"x":14903.173182942546,"y":11056.119330783491},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"87a28762-63d0-45f7-bd39-9dea436d8244","savedPayload":{"position":{"x":14903.173182942546,"y":11056.119330783491},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c4e402d7-5228-408c-9d67-379d6ef40bae","savedPayload":{"position":{"x":14995.87828125503,"y":10770.802375894946},"targetPosition":{"x":14695.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"bfb0b514-3b9f-4e9a-85ca-d0ca714b09f6","savedPayload":{"position":{"x":14695.87828125503,"y":10770.802375894946},"targetPosition":{"x":14695.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Design Space","name":"My Design Space","project":"Superalgos","spaceStyle":{"type":"Space Style","name":"My Space Style","config":" {\n \"backgroundColor\": \"UI_COLOR.BLACK\",\n \"node\": {\n \"fontSize\": 16,\n \"imageSize\": 60,\n \"type\": {\n \"fontColor\": \"UI_COLOR.WHITE\"\n },\n \"name\": {\n \"fontColor\": \"UI_COLOR.WHITE\"\n },\n \"menuItem\": {\n \"backgroundColor\": \"UI_COLOR.BLACK\",\n \"fontColor\": \"UI_COLOR.WHITE\",\n \"fontSize\": 14,\n \"imageSize\": 14\n }\n }\n }","project":"Superalgos","id":"fad0e429-f7a7-4b62-a2a5-2ead29b8f695","savedPayload":{"position":{"x":25236.875,"y":8701.347826086958},"targetPosition":{"x":24936.875,"y":8701.347826086958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"spaceSettings":{"type":"Space Settings","name":"New Space Settings","config":"{\n \"node\": {\n \"distancePercentage\": 60,\n \"radiusPercentage\": 85,\n \"massPercentage\": 100,\n \"animationSteps\": 2, \n \"menuItem\": {\n \"widthPercentage\": 100,\n \"heightPercentage\": 60,\n \"radiusPercentage\": 90\n }\n },\n \"physics\": false\n}","project":"Superalgos","id":"05c9d6d5-24c4-4eec-9aca-9668d6486fdd","savedPayload":{"position":{"x":24636.875,"y":8701.347826086958},"targetPosition":{"x":24936.875,"y":8701.347826086958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f8485ce5-67f3-4476-b9e2-80994e49c318","savedPayload":{"position":{"x":24940.875,"y":10745.347826086958},"targetPosition":{"x":24940.875,"y":10745.347826086958},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":255,"y":588.3125}}}},{"type":"Superalgos Project","name":"New Superalgos Project","project":"Superalgos","projectDefinition":{"type":"Project Definition","name":"Superalgos","config":"{\n \"codeName\": \"Superalgos\"\n}","project":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb","savedPayload":{"position":{"x":19378,"y":10727.5},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"spaces":{"type":"Spaces","name":"New Spaces","project":"Superalgos","id":"4d0ee814-4e48-4688-9cc5-7ee03de5192b","savedPayload":{"position":{"x":18810.69804274349,"y":10863.697149921863},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"trading":{"type":"Trading","name":"New Trading","project":"Superalgos","id":"0dcf22f9-cec5-48b5-b6c1-eb93d75c0055","savedPayload":{"position":{"x":18778.92479988006,"y":10751.037728718353},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"otherHierarchies":{"type":"Other Hierarchies","name":"New Other Hierarchies","project":"Superalgos","id":"228d01b9-466f-4374-afdd-15fff0426fab","savedPayload":{"position":{"x":18786.289023880698,"y":10657.466390843229},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cf9f8b3b-77c6-43c6-b01f-95cf366a91f6","savedPayload":{"position":{"x":19078,"y":10727.5},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Tutorial","name":"Basic Education","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back to School!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Nodes Menu","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Arrangement Features","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Pins","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Start With the Menu","config":"{\n \"icon\": {\n \"name\": \"unpinned-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Start With the Menu\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"117e0e8d-77c2-4ee9-b29f-d82f7b6f6995","savedPayload":{"position":{"x":25490.027487270225,"y":39634.40851272507},"targetPosition":{"x":25536.957826782294,"y":39930.71501490362},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Session Base Asset","name":"","id":"fb252bd6-3e7d-49a0-9fc6-be392be5db5b"}}},{"type":"Tutorial Step","name":"Pinned Nodes Can't Dance","config":"{\n \"icon\": {\n \"name\": \"pinned-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Pinned Nodes Can't Dance\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"734c6647-9e74-4d72-a621-29e0ff3e0bd3","savedPayload":{"position":{"x":25606.991435939068,"y":39639.00403878431},"targetPosition":{"x":25536.957826782294,"y":39930.71501490362},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"c69e3a63-8d67-4e41-b16e-39a88a9776e3","savedPayload":{"position":{"x":25536.957826782294,"y":39930.71501490362},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Angle to Parent","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Mary Go Round","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-360-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Mary Go Round\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"836a107b-368d-4ef0-8a43-5daeefcb0fe2","savedPayload":{"position":{"x":25886.240655911173,"y":40433.23445084565},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"180 Degrees","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-180-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - 180 Degrees\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"d9f1b166-20de-4ee5-94f7-0f9f363a5a82","savedPayload":{"position":{"x":25941.41057881172,"y":40509.16933527975},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Node's Independence","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-90-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Node's Independence\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c941ec5d-dcf0-48d5-a67b-5ce312c70470","savedPayload":{"position":{"x":25970.41512373375,"y":40598.43614568955},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Free-range Nodes","config":"{\n \"icon\": {\n \"name\": \"remove-angle-to-parent-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Free-range Nodes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"1b8726e1-8fa5-4584-8906-5c084785f476","savedPayload":{"position":{"x":25970.41512373375,"y":40692.29682471368},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"0a6ecc28-5731-49a1-878d-c1d2656cbecc","savedPayload":{"position":{"x":25706.338469709655,"y":40006.12813587088},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Distance to Parent","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Controlling Distances","config":"{\n \"icon\": {\n \"name\": \"set-distance-to-parent-node-to-one\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Controlling Distances\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e1a511e3-e833-4dcb-882c-28517b6fbaa2","savedPayload":{"position":{"x":26046.281424608744,"y":39996.77620519132},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"Play With The Tape!","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Play With The Tape!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"9ea33644-954d-475a-b3a1-9bca07951e58","savedPayload":{"position":{"x":26092.48784824228,"y":40104.32456902345},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"How About The Hierarchy?","config":"{\n \"icon\": {\n \"name\": \"set-distance-to-parent-node-to-one-and-a-half\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How About The Hierarchy?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"88ef7405-4f63-42a7-b02c-19f52b8f7576","savedPayload":{"position":{"x":26094.020040291325,"y":40221.36873391642},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Network","name":"My Network","id":"3c165071-7558-4708-9999-8ffe71d346b1"}}}],"tutorialTopics":[],"id":"c02373f4-3bf5-4b99-8dce-a152af6ec770","savedPayload":{"position":{"x":25799.043568022138,"y":40166.698076268774},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Arrangement Style","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Arrangement Style","config":"{\n \"icon\": {\n \"name\": \"set-node-arrangement-to-concave\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Arrangement Style\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"b03d5c5f-0ee9-48bf-a164-ce60a23b163f","savedPayload":{"position":{"x":26079.560122587445,"y":40358.9456609292},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Shall We Improve This? ","config":"{\n \"icon\": {\n \"name\": \"set-node-arrangement-to-concave\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Shall We Improve This?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"90b822dd-2f06-4474-a728-3500f3a30af4","savedPayload":{"position":{"x":26053.726562387557,"y":40473.113569359586},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Freeze","config":"{\n \"icon\": {\n \"name\": \"freeze-structure-of-nodes\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Freeze!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"2e3e7d2f-35ba-4620-b62a-f18d55e30989","savedPayload":{"position":{"x":25986.169297802902,"y":40568.70488774053},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Design Space","name":"My Design Space","id":"f8485ce5-67f3-4476-b9e2-80994e49c318"}}}],"tutorialTopics":[],"id":"14dbd920-b2e0-4b8f-ae74-22d2a3077082","savedPayload":{"position":{"x":25779.662925094777,"y":40351.092576436844},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"3f1d0740-00c0-4818-b256-3280bd99ae74","savedPayload":{"position":{"x":25505.599287801997,"y":40229.0715835141},"targetPosition":{"x":25245.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Productivity Tools","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Intro","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Talk Backups","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Talk Backups\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"561b5fd8-43dd-42cf-9230-c098ebc7e176","savedPayload":{"position":{"x":25851.150517837592,"y":40156.65592801336},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},{"type":"Tutorial Step","name":"Working With Versions","config":"{\n \"icon\": {\n \"name\": \"hand-drag\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Working With Versions\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e60db488-cf9d-4bb0-b1a8-0d66ef657613","savedPayload":{"position":{"x":25973.52309136077,"y":40210.04653605334},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Parameters","name":"New Parameters","id":"e79ab7df-ba40-46aa-abcd-63df8031a931"}}},{"type":"Tutorial Step","name":"Detaching and Attaching","config":"{\n \"icon\": {\n \"name\": \"detach-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Detaching and Attaching\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"ae239506-f063-4e2f-8933-9f44dcc40fe2","savedPayload":{"position":{"x":26060.6116537401,"y":40311.245281501426},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Attaching The Backup","config":"{\n \"icon\": {\n \"name\": \"mouse-right-click\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Attaching The Backup\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"cbdcbdcc-5f47-40a0-870c-ad71d0d12079","savedPayload":{"position":{"x":26095.16724712524,"y":40440.208511700446},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Detached Nodes Don't Count","config":"{\n \"icon\": {\n \"name\": \"detach-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Irrelevant Nodes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"60c572fe-8649-46eb-921e-4815fb9419b1","savedPayload":{"position":{"x":26070.34571244971,"y":40571.39347727926},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Nodes' Attaching Rules","config":"{\n \"icon\": {\n \"name\": \"help\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Nodes' Attaching Rules\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"14d77d4f-ae2a-41ca-bcf1-d60044ac45a8","savedPayload":{"position":{"x":25991.063259072154,"y":40678.81738692698},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Parameters","name":"New Parameters","id":"e79ab7df-ba40-46aa-abcd-63df8031a931"}}}],"tutorialTopics":[],"id":"c63ac428-2adf-4189-8560-5129c15ea793","savedPayload":{"position":{"x":25795.377035688718,"y":40451.425869983344},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"References","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dealing with References","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Dealing with References\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"References\"\n }\n }\n}","project":"Superalgos","id":"2733bece-0fd3-4846-9f88-8a95bf4f96f8","savedPayload":{"position":{"x":26003.4129110247,"y":40496.44315481149},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Let's See Some References","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's See Some References\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"775cc223-54d4-47e4-9863-a44e09dc2ff4","savedPayload":{"position":{"x":26055.18465682405,"y":40601.425869983344},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"Visualizing References","config":"{\n \"icon\": {\n \"name\": \"key-r\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Visualizing References\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"5b81ad17-e34c-4eed-98f5-d45a84d6f812","savedPayload":{"position":{"x":26062.840367349472,"y":40718.22944118012},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Establishing References","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Establishing References\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"a5847b14-8e83-4f7f-bd1f-55c3ddc3a99b","savedPayload":{"position":{"x":26025.214530072662,"y":40829.0715835141},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System Reference","name":"Lightning Strike","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2"}}},{"type":"Tutorial Step","name":"Let's Get On With It!","config":"{\n \"icon\": {\n \"name\": \"mouse-right-click\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Get On With It!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Establish and Remove References\",\n \"anchor\": \"What If the Nodes Are Far Away or in Different Hierarchies?\"\n }\n }\n}","project":"Superalgos","id":"f4a434bf-93ac-4aae-9b1a-a5f3e510ed57","savedPayload":{"position":{"x":25948.035337639947,"y":40917.07758560147},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Is It Done?","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Is It Done?\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"6449893d-f990-47f3-97d1-089487e3c8b1","savedPayload":{"position":{"x":25843.052622468087,"y":40968.84933140082},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"One Last Point!","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - One Last Point!\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"ae02f7ce-5dc4-4014-b385-5405e915c4c1","savedPayload":{"position":{"x":25726.249051271316,"y":40976.50504192625},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System Reference","name":"Lightning Strike","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2"}}}],"tutorialTopics":[],"id":"e837dc7b-f8e0-4c01-b6f2-87898c505c30","savedPayload":{"position":{"x":25765.40690893733,"y":40679.0715835141},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Backups & Clones","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Back to Backups!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back to Backups!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Backups\"\n }\n }\n}","project":"Superalgos","id":"49f383cc-5720-4f22-a444-6a12709be5da","savedPayload":{"position":{"x":25880.678459744897,"y":40858.00718906684},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Hammering Backups Home","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Hammering Backups Home\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"823bae09-4875-4b2c-b461-62b016247779","savedPayload":{"position":{"x":25843.052622468087,"y":40968.84933140082},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Task","name":"Lightning Strike","id":"08222935-2499-4a3e-a927-4f5dfbc392df"}}},{"type":"Tutorial Step","name":"Back It Up Again!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back It Up Again!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"8737b5cf-02ec-46d6-b6a3-705da85b00ce","savedPayload":{"position":{"x":25765.87343003537,"y":41056.855333488194},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},{"type":"Tutorial Step","name":"One Last Backup!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - One Last Backup!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"41e890ee-f42a-4396-9493-8298445b94b6","savedPayload":{"position":{"x":25660.89071486351,"y":41108.627079287544},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Point","name":"End Upper Band","id":"ff8660a3-65b0-4df3-b823-f0656537ea30"}}},{"type":"Tutorial Step","name":"No Need to Memorize","config":"{\n \"icon\": {\n \"name\": \"docs-warning-style\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - No Need to Memorize\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"d14e808a-d408-455b-be7b-0feb0c862662","savedPayload":{"position":{"x":25544.08714366674,"y":41116.28278981297},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"What About Clones?","config":"{\n \"icon\": {\n \"name\": \"clone-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - What About Clones?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Clones\"\n }\n }\n}","project":"Superalgos","id":"7942b504-e00b-4d78-b4a9-defd17ac6e08","savedPayload":{"position":{"x":25433.245001332754,"y":41078.656952536156},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Only Share Shares!","config":"{\n \"icon\": {\n \"name\": \"share-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Only Share Shares!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Shares\"\n }\n }\n}","project":"Superalgos","id":"39e09d3f-db3f-4961-9e32-915ba513a9a6","savedPayload":{"position":{"x":25345.238999245383,"y":41001.47776010344},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"974c84fb-0112-4a8b-9f53-6d057b22a073","savedPayload":{"position":{"x":25583.245001332754,"y":40818.84933140082},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"id":"338435fb-8de8-47e5-a51c-891399879226","savedPayload":{"position":{"x":25505.599287801997,"y":40529.0715835141},"targetPosition":{"x":25245.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"22c3e696-b371-48f9-814b-74a883ba6e7c","savedPayload":{"position":{"x":25245.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Workspaces","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Working with Workspaces","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Working with Workspaces\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Workspaces\"\n }\n }\n}","project":"Superalgos","id":"cd7b285d-22bf-4b30-82c1-4aade52c9dfe","savedPayload":{"position":{"x":25385.569414553385,"y":40716.52491818019},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Your Workspace vs Plugins","config":"{\n \"icon\": {\n \"name\": \"plugins\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Your Workspace vs Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Plugin Workspaces\"\n }\n }\n}","project":"Superalgos","id":"fa5f23d3-3a4b-4b29-9e16-f9d251678272","savedPayload":{"position":{"x":25245.791666666664,"y":40898.68682578477},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"The Current Workspace","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - The Current Workspace\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"78deb6f1-5589-4b91-ad96-d4397fafd6fd","savedPayload":{"position":{"x":25018.145953135907,"y":40928.656952536156},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Workspace","name":"Basic Education","id":"979bbac5-358b-427c-95d6-2b1df435d74e"}}}],"tutorialTopics":[],"id":"ad149fde-4bf0-4b26-b4a5-809fc8ba62e1","savedPayload":{"position":{"x":25095.791666666664,"y":40638.879204649435},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Plugins","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Talk Plugins","config":"{\n \"icon\": {\n \"name\": \"plugins\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Talk Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"366bcfde-71f9-4173-a80f-8fd4f5d7abcf","savedPayload":{"position":{"x":24978.42009536928,"y":40876.885206736806},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugins","name":"New Plugins","id":"bfb0b514-3b9f-4e9a-85ca-d0ca714b09f6"}}},{"type":"Tutorial Step","name":"How Plugins Work","config":"{\n \"icon\": {\n \"name\": \"expand-structure-of-nodes\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How Plugins Work\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"3e106105-19ca-4a7d-8915-c2ea46d92cec","savedPayload":{"position":{"x":24873.43738019742,"y":40928.656952536156},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Positioning Plugins","config":"{\n \"icon\": {\n \"name\": \"plugin-file-position\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Positioning Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"298ab522-ebbc-4b94-8fca-bce27208f8a2","savedPayload":{"position":{"x":24756.63380900065,"y":40936.31266306158},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugin File Position","name":"Masters-Lightning-Strike","id":"37ab4b0d-6bd8-46b6-9778-e193c32669a4"}}},{"type":"Tutorial Step","name":"Placing Plugins","config":"{\n \"icon\": {\n \"name\": \"plugin-trading-systems\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Placing Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"89958980-e536-414d-a55b-25149b6ebca2","savedPayload":{"position":{"x":24645.791666666664,"y":40898.68682578477},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugin Trading Systems","name":"New Plugin Trading Systems","id":"3569d452-c593-4e54-a356-7ff8c6b519f3"}}},{"type":"Tutorial Step","name":"Non-Persistence of Changes","config":"{\n \"icon\": {\n \"name\": \"bullet-error\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Non-Persistence of Changes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"2658f4f8-46df-4a83-9a39-6327553ba244","savedPayload":{"position":{"x":24557.785664579293,"y":40821.50763335205},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Starting From a Plugin","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Starting From a Plugin\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"286d6e2a-0020-4461-98e4-974315326ddd","savedPayload":{"position":{"x":24506.013918779943,"y":40716.52491818019},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Improving a Plugin","config":"{\n \"icon\": {\n \"name\": \"sensor-bot\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Improving a Plugin\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"4a1b74f7-8ed5-4771-b0e0-3d1427a5510a","savedPayload":{"position":{"x":24498.35820825452,"y":40599.72134698342},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"73a666a2-268d-42d1-ac73-e7ae316542e7","savedPayload":{"position":{"x":24795.791666666664,"y":40638.879204649435},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Exchanges","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Talking Exchanges","config":"{\n \"icon\": {\n \"name\": \"crypto-exchange\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Talking Exchanges\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Community Effort to Test Exchanges\"\n }\n }\n}","project":"Superalgos","id":"70ece243-3a2a-4b2a-9963-5044c11df654","savedPayload":{"position":{"x":24433.6596323107,"y":40591.203617870066},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Testing New Exchanges","config":"{\n \"icon\": {\n \"name\": \"crypto-exchange\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Testing New Exchanges\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"How to Test New Exchanges\"\n }\n }\n}","project":"Superalgos","id":"11a7025e-6b0b-4ac3-9994-e014b1980b08","savedPayload":{"position":{"x":24345.791666666664,"y":40379.0715835141},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Clean Workspace","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Clean Workspace\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"57edeba5-84fb-4ae2-bbf8-c16f71c842c1","savedPayload":{"position":{"x":24433.6596323107,"y":40166.93954915814},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"3bba7ba9-7d4c-4d84-9c25-307f59bd7670","savedPayload":{"position":{"x":24645.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Data","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dealing With Data","config":"{\n \"icon\": {\n \"name\": \"dataset-definition\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Dealing With Data\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"811af117-7a9f-4522-a391-f310fcab8167","savedPayload":{"position":{"x":24495.791666666664,"y":40119.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"About Other Markets","config":"{\n \"icon\": {\n \"name\": \"market\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - About Other Markets\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"7eb3bc72-7230-4c9a-bc7d-a568d3cc2465","savedPayload":{"position":{"x":24535.98404553133,"y":39969.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Exchange Markets","name":"New Exchange Markets","id":"2fd80894-900e-44ac-a1a7-56c14124f7a1"}}},{"type":"Tutorial Step","name":"Building Indicators","config":"{\n \"icon\": {\n \"name\": \"indicator-bot\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Building Indicators\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"How to Build an Indicator - Video Series\"\n }\n }\n}","project":"Superalgos","id":"bbdede43-5ebe-4438-969e-e56fb8d36af7","savedPayload":{"position":{"x":24645.791666666664,"y":39859.456341243436},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"More Indicators?","config":"{\n \"icon\": {\n \"name\": \"data-mine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - More Indicators?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Book\",\n \"type\": \"Community Data Mines\"\n }\n }\n}","project":"Superalgos","id":"fd066dc6-57fb-4121-b8e7-1edc06bdf3a0","savedPayload":{"position":{"x":24795.791666666664,"y":39819.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"How About Strategies?","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How About Strategies?\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c18673fd-a8cf-4aba-b89b-d38d96991c82","savedPayload":{"position":{"x":24945.791666666664,"y":39859.456341243436},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"2c2b7b0c-de6e-480d-93d2-27bbb74b972b","savedPayload":{"position":{"x":24795.791666666664,"y":40119.26396237877},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"End","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Your Graduation","config":"{\n \"icon\": {\n \"name\": \"trading-strategy\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Your Graduation\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"2c47bc65-09a1-4576-a69c-990e47930ac5","savedPayload":{"position":{"x":25245.791666666664,"y":39859.456341243436},"targetPosition":{"x":25095.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}}],"tutorialTopics":[],"id":"0f058d80-353d-4073-8b41-805938e1551e","savedPayload":{"position":{"x":25095.791666666664,"y":40119.26396237877},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"id":"987e20ec-bf08-488c-92ec-7ef6e8b79ef8","savedPayload":{"position":{"x":24945.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial","name":"Contribute to Superalgos","config":"{\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"documentationURL\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial - Wanna Help? Come On In!\"\n },\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Intro","config":"{\n \"position\": \"\",\n \"pressButton\": \"Next\",\n \"documentationURL\": \"\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"You are in command","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - You Are In Command\"\n },\n \"icon\": {\n \"name\": \"strategy-manage-stage\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"cf295c5b-14f3-4440-b684-c9a429110269","savedPayload":{"position":{"x":31497,"y":40092.69237886467},"targetPosition":{"x":31347,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Free For Everyone?","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Free For Everyone?\"\n },\n \"icon\": {\n \"name\": \"help\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"64170c58-8848-453c-8bb9-ea8483476b6d","savedPayload":{"position":{"x":31606.807621135333,"y":40202.5},"targetPosition":{"x":31347,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"A Brilliant Idea","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - A Brilliant Idea\"\n },\n \"icon\": {\n \"name\": \"nodes-highlights\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"4a969dfa-6c68-4eb5-98c3-c20f2b9bebbc","savedPayload":{"position":{"x":31647,"y":40352.5},"targetPosition":{"x":31347,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"What is a Contribution?","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - What is a Contribution?\"\n },\n \"icon\": {\n \"name\": \"execution-algorithm\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"556f8af1-63ae-423a-a5fe-5720e7b4ae96","savedPayload":{"position":{"x":31606.807621135333,"y":40502.5},"targetPosition":{"x":31347,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"What About Free Riders?","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - What About Free Riders?\"\n },\n \"icon\": {\n \"name\": \"bullet-error\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"ca46f639-4472-420d-a647-2c3be58a6f4b","savedPayload":{"position":{"x":31497,"y":40612.30762113533},"targetPosition":{"x":31347,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}}],"tutorialTopics":[],"id":"2fefbfbf-c5e3-4da4-82b6-a36e5fb1edcd","savedPayload":{"position":{"x":31347,"y":40352.5},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Branches","config":"{\n \"position\": \"\",\n \"pressButton\": \"Next\",\n \"documentationURL\": \"\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Switching Branches","config":"{\n \"icon\": {\n \"name\": \"github\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Switching Branches\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"searchPage\": true,\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"c3dc484a-9bf2-47f2-aafe-56abd3dbe8ea","savedPayload":{"position":{"x":31438.780298432423,"y":40661.3546836069},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Now the Current Branch","config":"{\n \"icon\": {\n \"name\": \"github\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Now the Current Branch\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"c755cfee-f1b5-47a1-8c72-f7bd1285ed5d","savedPayload":{"position":{"x":31407.007055568993,"y":40774.01410481041},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Before You Switch","config":"{\n \"icon\": {\n \"name\": \"bullet-warning\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Before You Switch\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c5186485-0efc-4ced-b670-a012564ffe0d","savedPayload":{"position":{"x":31334.539512811538,"y":40865.93874456856},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Double Trouble?","config":"{\n \"icon\": {\n \"name\": \"clone-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Double Trouble?\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": false\n }\n}","project":"Superalgos","id":"b9110aee-2bb4-4930-a6b3-d3b14d4d62d3","savedPayload":{"position":{"x":31232.410196624965,"y":40923.1339097771},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Let's Switch Already!","config":"{\n \"icon\": {\n \"name\": \"docs-success-style\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Switch Already!\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true,\n \"searchPage\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"014163bf-692e-40dc-be33-8bbba811310d","savedPayload":{"position":{"x":31116.167369594128,"y":40936.892155008485},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Welcome Back!","config":"{\n \"icon\": {\n \"name\": \"hits\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Welcome Back!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"7cfebeab-bd19-4caf-af9c-60eda4325bc7","savedPayload":{"position":{"x":31003.50794839062,"y":40905.11891214506},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Update the App!","config":"{\n \"icon\": {\n \"name\": \"indicator-process-instance\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Update the App!\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"08e24e17-777d-45bc-887d-e68d734ef751","savedPayload":{"position":{"x":30911.583308632475,"y":40832.651369387604},"targetPosition":{"x":31139.705098312483,"y":40637.81695488855},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"65f4de98-58c6-44b1-9c61-46aa0a45a71c","savedPayload":{"position":{"x":31139.705098312483,"y":40637.81695488855},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Editing","config":"{\n \"position\": \"\",\n \"pressButton\": \"Next\",\n \"documentationURL\": \"\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Add Your Review!","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Add Your Review!\"\n },\n \"icon\": {\n \"name\": \"expand-structure-of-nodes\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"a49ea1fc-8cfe-41a1-a781-860e294cf1f6","savedPayload":{"position":{"x":30857.86197012711,"y":40824.01445226733},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Did It Work?","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Did It Work?\"\n },\n \"icon\": {\n \"name\": \"docs-action-edit-paragraph\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"3803ec52-574c-4961-8366-551ed8abd757","savedPayload":{"position":{"x":30724.483848017513,"y":40818.0244338965},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Breaking Up The Command","config":"{\n \"icon\": {\n \"name\": \"copy-path\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Breaking Up The Command\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c23381c5-d2e3-4b19-9065-8401c0e024d6","savedPayload":{"position":{"x":30606.913283905604,"y":40754.75701548882},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Editing Crash Course","config":"{\n \"icon\": {\n \"name\": \"docs-action-edit-paragraph\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Editing Crash Course\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"686bdf5e-b7a5-4237-9779-f806c0d93065","savedPayload":{"position":{"x":30528.436569922083,"y":40646.743085183916},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Don't Forget to Sign!","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Don't Forget to Sign!\"\n },\n \"icon\": {\n \"name\": \"bullet-warning\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"ef70642b-3699-4101-bb45-7c76cf125af3","savedPayload":{"position":{"x":30504.596981725124,"y":40515.37612658259},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}},{"type":"Tutorial Step","name":"Don't Forget to Save!","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Don't Forget to Save!\"\n },\n \"icon\": {\n \"name\": \"under-construction\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"d61352ca-f701-4403-af3f-dcbfcd05b402","savedPayload":{"position":{"x":30540.116242130494,"y":40386.67497694584},"targetPosition":{"x":30804.294901687517,"y":40528.83557568774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}}],"tutorialTopics":[],"id":"8bd606bc-a0bd-47e3-99df-a53bf79e0bb9","savedPayload":{"position":{"x":30804.294901687517,"y":40528.83557568774},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"GitHub","config":"{\n \"position\": \"Left\",\n \"pressButton\": \"Next\",\n \"documentationURL\": \"\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Get Ready to Push!","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Get Ready to Push!\"\n },\n \"icon\": {\n \"name\": \"github\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"7859f5c1-bba6-405a-9b62-ec086b59be27","savedPayload":{"position":{"x":30561.589803375035,"y":40352.5},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Translation for Mere Mortals","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Translation for Mere Mortals\"\n },\n \"icon\": {\n \"name\": \"github\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"c35d39f0-5c90-48fd-badc-592be51a8605","savedPayload":{"position":{"x":30518.977946798972,"y":40268.869522624744},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Contributable files?","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Contributable files?\"\n },\n \"icon\": {\n \"name\": \"dataset\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"a2846838-6234-4fb1-8f28-2ce5a69607d4","savedPayload":{"position":{"x":30504.294901687517,"y":40176.16442431226},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"GitHub.com Authentication","config":"{\n \"position\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - GitHub.com Authentication\"\n },\n \"icon\": {\n \"name\": \"github-api\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"5934eb7c-d208-498e-9bce-fca825fa129c","savedPayload":{"position":{"x":30518.977946798972,"y":40083.45932599977},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"GitHub.com Auth Clip","config":"{\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - GitHub.com Auth Clip\"\n },\n \"icon\": {\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"ec8aca7b-50a2-4635-b0db-f3ed2c2796e3","savedPayload":{"position":{"x":30561.589803375035,"y":39999.828848624515},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Set Up the Token!","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"positionAtReferenceParent\": true,\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Set Up the Token!\"\n },\n \"icon\": {\n \"name\": \"github-api\",\n \"project\": \"Superalgos\"\n }\n}","project":"Superalgos","id":"f7b3489d-a282-4e12-a28d-6300619713f5","savedPayload":{"position":{"x":30627.959325999775,"y":39933.45932599977},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Github API","name":"New Github API","id":"9ea7bee2-c4db-4cee-a05f-63fcf3a86a4a"}}},{"type":"Tutorial Step","name":"A Note On Keys and Tokens!","config":"{\n \"position\": \"Left\",\n \"positionAtReferenceParent\": true,\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - A Note On Keys and Tokens!\"\n },\n \"icon\": {\n \"name\": \"exchange-account-key\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"f7cd63ca-f5bd-4f92-ad8b-ec65ee5efe44","savedPayload":{"position":{"x":30711.589803375035,"y":39890.84746942371},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Let's Run the Command!","config":"{\n \"position\": \"Left\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Run the Command!\"\n },\n \"icon\": {\n \"name\": \"docs-json-code-style\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"searchPage\": true,\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"79cc032d-7cdc-4b3a-ac77-7ed2d2bbed06","savedPayload":{"position":{"x":30804.294901687517,"y":39876.16442431226},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Congrats and Thank You!","config":"{\n \"position\": \"Left\",\n \"positionAtReferenceParent\": true,\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Congrats and Thank You!\"\n },\n \"icon\": {\n \"name\": \"docs-success-style\",\n \"project\": \"Superalgos\"\n },\n \"controlDocs\": {\n \"closeTutorialEditor\": true\n }\n}","project":"Superalgos","id":"7793d0b5-b468-4e4f-aff0-e4b43cf01925","savedPayload":{"position":{"x":30897,"y":39890.84746942371},"targetPosition":{"x":30804.294901687517,"y":40176.16442431226},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"924146dc-0d92-41ad-9de8-8b341e379fb2","savedPayload":{"position":{"x":30804.294901687517,"y":40176.16442431226},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"End","config":"{\n \"position\": \"Left\",\n \"pressButton\": \"Next\",\n \"documentationURL\": \"\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"More on Contributions","config":"{\n \"icon\": {\n \"name\": \"execution-algorithm\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - More on Contributions\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"af57eaca-ba68-4f71-9bb0-b5f825de2e49","savedPayload":{"position":{"x":31077.331591067155,"y":39773.738764891306},"targetPosition":{"x":31139.705098312483,"y":40067.18304511145},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"A Book on Tutorials","config":"{\n \"icon\": {\n \"name\": \"scripts-library\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - A Book on Tutorials\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Book\",\n \"type\": \"First Steps Tutorials\"\n }\n }\n}","project":"Superalgos","id":"440515fe-9612-4c12-9180-638cc37b75bb","savedPayload":{"position":{"x":31362.6485459557,"y":39866.44386320379},"targetPosition":{"x":31139.705098312483,"y":40067.18304511145},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"b34d468c-ec85-489c-b6a7-28862c0956c6","savedPayload":{"position":{"x":31139.705098312483,"y":40067.18304511145},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"id":"a8711464-9e92-4e16-9622-a1b499a856ca","savedPayload":{"position":{"x":31047,"y":40352.5},"targetPosition":{"x":31047,"y":40352.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial","name":"Setting up a new Chart","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Introduction\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Getting Started","config":"{\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Before we begin","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Before We Begin\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c8304d44-191c-49c8-a982-88a5ea42b395","savedPayload":{"position":{"x":19758.164424312257,"y":40103.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Charts without tears","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Charts without tears\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"a2d5c58d-1aa9-4958-9aca-0e5fcc806e2f","savedPayload":{"position":{"x":20058.164424312257,"y":40403.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Charting Space","name":"New Charting Space","id":"21d2ec55-9e56-4652-8e96-c7e451262c36"}}},{"type":"Tutorial Step","name":"Looking for a quick fix?","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Looking for a quick fix?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"d9407975-f8f8-42fe-b4c4-f0589471cdf8","savedPayload":{"position":{"x":19758.164424312257,"y":40703.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Network Node","name":"My Computer","id":"e452cf65-2b2b-44f2-9e67-bdd9d3c008e4"}}}],"tutorialTopics":[],"id":"c30627fc-e01f-48bd-8347-99c1b13b0088","savedPayload":{"position":{"x":19758.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Dashboards and Time Machines","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dashing Dashboards","config":"{\n \"icon\": {\n \"name\": \"dashboard\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Dashing Dashboards\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e902be8c-fe3e-463a-b429-1dec70cb12b4","savedPayload":{"position":{"x":19867.97204544759,"y":40513.60252282285},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Charting Space","name":"New Charting Space","id":"21d2ec55-9e56-4652-8e96-c7e451262c36"}}},{"type":"Tutorial Step","name":"Time Machines hold it all together","config":"{\n \"icon\": {\n \"name\": \"time-machine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Time Machines hold it all together\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Node\",\n \"type\": \"Time Machine\"\n }\n }\n}","project":"Superalgos","id":"fa55dca7-9a95-4e4c-a3c1-571d1aac5ebf","savedPayload":{"position":{"x":19758.164424312257,"y":40923.41014395818},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Keep it in one place","config":"{\n \"icon\": {\n \"name\": \"time-machine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Keep it in one place\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"da032cf6-441b-4a53-a968-49f97c0a1c5b","savedPayload":{"position":{"x":19348.356803176925,"y":40813.60252282285},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Dashboard","name":"Testing Environment My Computer","id":"885265c2-ebb1-4283-a617-34a88780276d"}}}],"tutorialTopics":[],"id":"c8d6c07d-70c6-4999-b77b-155f5bf07dac","savedPayload":{"position":{"x":19608.164424312257,"y":40663.60252282285},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Your first custom Chart","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Add the Chart","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Without Further Ado","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Without Further Ado\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"ea3312d6-88fc-4e7a-9ae5-9620e3bddfdd","savedPayload":{"position":{"x":19597.94217219898,"y":41165.51230506553},"targetPosition":{"x":19385.810137843015,"y":40953.38027070957},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Why is it blank?","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Why is it blank?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"a2131ede-c79b-4313-bd85-40fbd29287e7","savedPayload":{"position":{"x":19308.164424312257,"y":41243.15801859629},"targetPosition":{"x":19385.810137843015,"y":40953.38027070957},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}}],"tutorialTopics":[],"id":"f46dff3b-4bc8-46f0-a581-a8bf72c7f1e2","savedPayload":{"position":{"x":19385.810137843015,"y":40953.38027070957},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Managing Layers","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"The Chart of many talents","config":"{\n \"icon\": {\n \"name\": \"timeline-chart\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - The Chart of many talents\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c0c76521-31f9-474a-862e-40afc6507f9d","savedPayload":{"position":{"x":19158.164424312257,"y":41223.41014395818},"targetPosition":{"x":19158.164424312257,"y":40923.41014395818},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Herding layers","config":"{\n \"icon\": {\n \"name\": \"layer-manager\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Herding layers\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"426ca9c5-6476-4c7f-bb34-af88b41de96e","savedPayload":{"position":{"x":18898.356803176925,"y":41073.41014395818},"targetPosition":{"x":19158.164424312257,"y":40923.41014395818},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}}],"tutorialTopics":[],"id":"875b6687-2c74-4dff-9f62-96c342298b59","savedPayload":{"position":{"x":19158.164424312257,"y":40923.41014395818},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Working with Data Storage","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Your data treasure trove","config":"{\n \"icon\": {\n \"name\": \"data-storage\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Your data treasure trove\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"8ef69b83-1314-4f88-bfbb-fa4ae7aaf4c9","savedPayload":{"position":{"x":18868.386676425536,"y":41001.05585748894},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Data Storage","name":"New Data Storage","id":"e2697759-6038-4943-b90c-5a68651ff9a8"}}},{"type":"Tutorial Step","name":"Follow the Tree!","config":"{\n \"icon\": {\n \"name\": \"data-mines-data\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Follow the Tree!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"57ee6e8b-b8b4-4d79-b0b6-e80e9bbff001","savedPayload":{"position":{"x":18728.608928538815,"y":40818.89394988436},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Dashboard","name":"Testing Environment My Computer","id":"885265c2-ebb1-4283-a617-34a88780276d"}}},{"type":"Tutorial Step","name":"The data you want to see","config":"{\n \"icon\": {\n \"name\": \"data-storage\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - The data you want to see\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"b12414e1-02e3-4b84-abf1-c56eef5ccc3a","savedPayload":{"position":{"x":18758.579055290204,"y":40591.248236353604},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a new Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}}],"tutorialTopics":[],"id":"ca9d3427-37c7-4559-a1ac-6004aa913562","savedPayload":{"position":{"x":19018.386676425536,"y":40741.248236353604},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"1246dd21-45b1-4664-845f-ccea597a602e","savedPayload":{"position":{"x":19308.164424312257,"y":40663.60252282285},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Connecting to Data Mine Products","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Hooking up a Chart to Data Products","config":"{\n \"icon\": {\n \"name\": \"data-mine-products\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Hooking up a Chart to Data Products\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"cc2794e2-9140-4ca5-89d0-c812eee41f6d","savedPayload":{"position":{"x":19250.86952262474,"y":40689.11185657606},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Data Products make the world go round","config":"{\n \"icon\": {\n \"name\": \"data-mine-products\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Data Products make the world go round\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"67529836-d0a7-4a27-8b09-63f599a7c03f","savedPayload":{"position":{"x":18915.459325999775,"y":40580.130477375256},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Make the connection","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Make the connection\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"4b347096-6bcd-45f3-b40d-6fcd6b3837eb","savedPayload":{"position":{"x":18915.459325999775,"y":40227.45932599977},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Add the Layers","config":"{\n \"icon\": {\n \"name\": \"layer\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Add the Layers\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"f0411061-33a3-4f21-ad4e-670f8381f209","savedPayload":{"position":{"x":19250.86952262474,"y":40118.477946798965},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"d4893496-189d-4fe8-a6b1-864dcd9a46b6","savedPayload":{"position":{"x":19158.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Connecting to Trading Mine Products","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Hooking up a Chart to a Trading System","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Hooking up a Chart to a Trading System\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"cedbe86a-bf7b-4f1d-95dd-641198dc2146","savedPayload":{"position":{"x":19107.4252424046,"y":40366.9307281954},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Connection one","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Connection one\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"68c45d99-618b-4371-8e93-b81d80d60dde","savedPayload":{"position":{"x":19034.100787019477,"y":40021.96628762944},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Connection two","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Connection two\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c7b0d632-79d4-4c8b-a991-67298d30016f","savedPayload":{"position":{"x":19339.522963292555,"y":39845.630711941696},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Check the Chart","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Check the Chart\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c8bebdf9-b4b5-4737-aeff-4a578389c810","savedPayload":{"position":{"x":19601.6087045324,"y":40081.61377330685},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"ab24e3dc-c131-4a6d-a1a0-7df304237185","savedPayload":{"position":{"x":19308.164424312257,"y":40143.98728055218},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Before I go","config":"{\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Easy as 1,2,3","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Easy as 1, 2, 3\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"88edf6e9-f780-4e0f-b031-cbe2bc2cfdaf","savedPayload":{"position":{"x":19458.164424312257,"y":39884.17965941685},"targetPosition":{"x":19608.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Before I go","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Before I go\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"72bd2fd9-4de6-4bd4-bc9d-a9fba53d9827","savedPayload":{"position":{"x":19908.164424312257,"y":40143.98728055218},"targetPosition":{"x":19608.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"0570a00c-734e-44fb-9761-44ccb63212ff","savedPayload":{"position":{"x":19608.164424312257,"y":40143.98728055218},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"f87a4d66-cd01-4712-8ec6-c232677c5547","savedPayload":{"position":{"x":19458.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isPlaying":false,"isRunning":false},"tutorial":{"status":"Done"}}}]} \ No newline at end of file +{"type":"Workspace","name":"Creating Custom Charts","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataTasks":{"type":"Data Tasks","name":"New Data Tasks","project":"Superalgos","projectDataTasks":[{"type":"Project Data Tasks","name":"Superalgos","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binanceus","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"d244c564-4e86-43c7-9796-dc3b6294ec8b","savedPayload":{"position":{"x":26497.378634092645,"y":28190.39686701245},"targetPosition":{"x":26757.186255227978,"y":28040.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"343313ae-5705-484d-8bf8-aed25ba61cfa","savedPayload":{"position":{"x":26757.186255227978,"y":28040.39686701245},"targetPosition":{"x":27016.99387636331,"y":27890.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"a8f38508-1cac-4ab1-815f-d338fc813377","savedPayload":{"position":{"x":27016.99387636331,"y":27890.39686701245},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"f0ef12ed-f0fd-4b88-8e15-27cf24265a5f","savedPayload":{"position":{"x":26407.46825383848,"y":27662.75115348169},"targetPosition":{"x":26697.2460017252,"y":27585.105439950934},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7c8b312c-09bf-4c59-853f-1592391a9c57","savedPayload":{"position":{"x":26485.113967369238,"y":27372.97340559497},"targetPosition":{"x":26697.2460017252,"y":27585.105439950934},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"8d58e84b-d7ef-464f-8079-0ec0887e3da3","savedPayload":{"position":{"x":26697.2460017252,"y":27585.105439950934},"targetPosition":{"x":26987.023749611923,"y":27662.75115348169},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bf29e3bd-9386-408b-9091-042da0c53e81","savedPayload":{"position":{"x":26987.023749611923,"y":27662.75115348169},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Market","project":"Superalgos","id":"a707814e-b81b-4102-9b5b-4e2fe969324f","savedPayload":{"position":{"x":26716.99387636331,"y":27070.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"5d9b2729-43fb-4e7e-aa4f-b8477c424e51"}}},{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Daily","project":"Superalgos","id":"c5395fbe-4b5a-4492-a7fb-e2d259905e27","savedPayload":{"position":{"x":26976.801497498644,"y":26920.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"be19d91b-9337-4f84-96b3-f4e54ea12df5"}}}],"id":"112be2cf-74ea-4272-9566-cf0cd24c111c","savedPayload":{"position":{"x":26976.801497498644,"y":27220.781624741783},"targetPosition":{"x":27126.801497498644,"y":27480.589245877116},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e74c3232-7b59-4006-87fa-b3b2a328a52b","savedPayload":{"position":{"x":27126.801497498644,"y":27480.589245877116},"targetPosition":{"x":27276.801497498644,"y":27740.39686701245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c193ecbb-c3e0-4fd5-94ed-bb6356d1d5ea","savedPayload":{"position":{"x":27276.801497498644,"y":27740.39686701245},"targetPosition":{"x":27566.579245385365,"y":27818.042580543206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"85224e5e-f3ee-4e8d-b9bd-e5901bd49b33","savedPayload":{"position":{"x":27566.579245385365,"y":27818.042580543206},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Tasks","name":"Sparta","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Sparta","project":"Superalgos","tasks":[{"type":"Task","name":"Simple Moving Average (SMA)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Simple Moving Average (SMA)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Simple Moving Average (SMA) Multi-Period-Market","project":"Superalgos","id":"577e56c5-4bae-4528-8ed4-f7032a6cc2b2","savedPayload":{"position":{"x":26676.801497498644,"y":27220.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"456269f6-9849-4d5f-9c8c-7cd7d1eef297"}}},{"type":"Indicator Process Instance","name":"Simple Moving Average (SMA) Multi-Period-Daily","project":"Superalgos","id":"1ebcdf4e-828a-4fc6-8516-1fd1466f747f","savedPayload":{"position":{"x":26716.99387636331,"y":27070.781624741783},"targetPosition":{"x":26976.801497498644,"y":27220.781624741783},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"333ae5d7-7ec1-4f08-b206-91e3b4f2c99f"}}}],"id":"78619a39-67e7-4be3-92d4-794e699bc134","savedPayload":{"position":{"x":26976.801497498644,"y":27220.781624741783},"targetPosition":{"x":27266.579245385365,"y":27298.42733827254},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c1c85b8e-3c0c-4527-b4c3-b8a9f2bfc22b","savedPayload":{"position":{"x":27266.579245385365,"y":27298.42733827254},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Moving Average Convergence Diveregence (MACD) Multi-Period-Market","project":"Superalgos","id":"f22238fe-0c4c-44bb-9a21-edc1b6ff4eb8","savedPayload":{"position":{"x":27044.224958916122,"y":26644.32577517667},"targetPosition":{"x":27256.356993272086,"y":26856.457809532632},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"44019efe-950a-4eec-a546-cd2ee26818b9"}}},{"type":"Indicator Process Instance","name":"Moving Average Convergence Diveregence (MACD) Multi-Period-Daily","project":"Superalgos","id":"9cc5b202-a9c4-4632-9c21-3b01a2f74255","savedPayload":{"position":{"x":27178.71127974133,"y":26566.68006164591},"targetPosition":{"x":27256.356993272086,"y":26856.457809532632},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"8e5db945-8507-4489-9288-21cfa1e9301c"}}}],"id":"4efb5b27-ab99-4e9a-a2a3-8990e8713fe2","savedPayload":{"position":{"x":27256.356993272086,"y":26856.457809532632},"targetPosition":{"x":27406.356993272086,"y":27116.265430667965},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"129e39d0-f14f-449f-96ba-b7c2f40ba33a","savedPayload":{"position":{"x":27406.356993272086,"y":27116.265430667965},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Relative Strenght Index (RSI)","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Relative Strenght Index (RSI)","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Relative Strenght Index (RSI) Multi-Period-Market","project":"Superalgos","id":"824c6e6f-65af-464b-948b-d529f5776982","savedPayload":{"position":{"x":27711.6484203336,"y":26496.517556029856},"targetPosition":{"x":27711.6484203336,"y":26796.517556029856},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"96f31416-5090-428a-be83-985a0b3ab275"}}},{"type":"Indicator Process Instance","name":"Relative Strenght Index (RSI) Multi-Period-Daily","project":"Superalgos","id":"ced7678d-e4c1-4891-be78-265d79aab04c","savedPayload":{"position":{"x":27861.6484203336,"y":26536.709934894523},"targetPosition":{"x":27711.6484203336,"y":26796.517556029856},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"f1177bcd-22dc-425b-8f30-878844aa82b8"}}}],"id":"1cacb36f-7b2a-499c-aeb0-a6b0a4a1969a","savedPayload":{"position":{"x":27711.6484203336,"y":26796.517556029856},"targetPosition":{"x":27634.002706802843,"y":27086.295303916577},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bbdf0a91-954a-422d-bff1-b4c206425006","savedPayload":{"position":{"x":27634.002706802843,"y":27086.295303916577},"targetPosition":{"x":27556.356993272086,"y":27376.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"172d0669-960d-47c7-aba9-8984b98389ac","savedPayload":{"position":{"x":27556.356993272086,"y":27376.073051803298},"targetPosition":{"x":27706.356993272086,"y":27635.88067293863},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b9dc8332-3efb-46a4-9e39-7fd204ac0173","savedPayload":{"position":{"x":27706.356993272086,"y":27635.88067293863},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Tasks","name":"Alpha","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Alpha","project":"Superalgos","tasks":[{"type":"Task","name":"Stochastic","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Stochastic","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Stochastic Multi-Period-Market","project":"Superalgos","id":"244f2d9d-0b4d-4a73-acac-b95c7f060c20","savedPayload":{"position":{"x":28166.939847395115,"y":26436.57730252708},"targetPosition":{"x":28166.939847395115,"y":26736.57730252708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"6a6a6533-21a9-4be9-b2f0-ace1adfe45b8"}}},{"type":"Indicator Process Instance","name":"Stochastic Multi-Period-Daily","project":"Superalgos","id":"93f3e4f4-1774-481a-be53-20c0c19fb54f","savedPayload":{"position":{"x":28316.939847395115,"y":26476.769681391746},"targetPosition":{"x":28166.939847395115,"y":26736.57730252708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"6a39c43d-0ad2-4c98-ae06-6e40f55d1753"}}}],"id":"8e66e327-a785-489b-ab0b-f3bc84546d1e","savedPayload":{"position":{"x":28166.939847395115,"y":26736.57730252708},"targetPosition":{"x":28089.294133864358,"y":27026.3550504138},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"66046624-d8cc-4d5b-a24a-4ce998353616","savedPayload":{"position":{"x":28089.294133864358,"y":27026.3550504138},"targetPosition":{"x":28011.6484203336,"y":27316.13279830052},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e66a0d4c-201f-4955-83d4-9e0a5308ad80","savedPayload":{"position":{"x":28011.6484203336,"y":27316.13279830052},"targetPosition":{"x":27934.002706802843,"y":27605.910546187242},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f4378a66-6833-4164-bec1-4f1c3b42d5b4","savedPayload":{"position":{"x":27934.002706802843,"y":27605.910546187242},"targetPosition":{"x":27856.356993272086,"y":27895.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Alpha","id":"511bef1e-62d8-4ff9-8d87-15bd0d3d630c"}}}],"id":"70d459d6-d270-49e0-b70d-2053c65a40e2","savedPayload":{"position":{"x":27856.356993272086,"y":27895.688294073963},"targetPosition":{"x":28006.356993272086,"y":28155.495915209296},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"af949a76-a6f4-4ec6-869e-f240480eea81","savedPayload":{"position":{"x":28006.356993272086,"y":28155.495915209296},"targetPosition":{"x":28156.356993272086,"y":28415.30353634463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"9b93b56d-dccf-4a8c-bbd0-8c608c31363c","savedPayload":{"position":{"x":28156.356993272086,"y":28415.30353634463},"targetPosition":{"x":28306.356993272086,"y":28675.11115747996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"40af91d9-431c-4b7d-addc-aed37bc2f3fe","savedPayload":{"position":{"x":28306.356993272086,"y":28675.11115747996},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"learningTasks":{"type":"Learning Tasks","name":"New Learning Tasks","project":"Superalgos","projectLearningTasks":[{"type":"Project Learning Tasks","name":"Superalgos","project":"Superalgos","exchangeLearningTasks":[],"id":"ddd4bf4d-46fd-4c16-86d3-1785f5ad629e","savedPayload":{"position":{"x":25559.356993272086,"y":30511.30353634463},"targetPosition":{"x":25409.356993272086,"y":30771.11115747996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"0818dfbe-61ea-40b8-8544-bee25d7f45be","savedPayload":{"position":{"x":28606.356993272086,"y":28675.11115747996},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"testingTradingTasks":{"type":"Testing Trading Tasks","name":"New Testing Trading Tasks","project":"Superalgos","projectTradingTasks":[{"type":"Project Trading Tasks","name":"Superalgos","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binanceus","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","tradingMineTasks":[{"type":"Trading Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Lightning Strike","project":"Superalgos","bot":{"type":"Trading Bot Instance","name":"Low Frequency","config":"{}","project":"Superalgos","processes":[{"type":"Trading Process Instance","name":"Low Frequency Trading","project":"Superalgos","session":{"type":"Backtesting Session","name":"Lightning Strike","config":"{\"folderName\":\"Lightning-Strike\"}","project":"Superalgos","tradingParameters":{"type":"Trading Parameters","name":"New Parameters","project":"Superalgos","sessionBaseAsset":{"type":"Session Base Asset","name":"","config":"{\n\"initialBalance\": 0,\n\"minimumBalance\": 0\n}","project":"Superalgos","id":"fb252bd6-3e7d-49a0-9fc6-be392be5db5b","savedPayload":{"position":{"x":31532.291877706186,"y":28455.48478700282},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"sessionQuotedAsset":{"type":"Session Quoted Asset","name":"","config":"{\n\"initialBalance\": 1000\n}","project":"Superalgos","id":"ed578090-732c-4e41-a4ae-9d4f34607170","savedPayload":{"position":{"x":31621.55868811598,"y":28426.48024208079},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeRange":{"type":"Time Range","name":"New Time Range","config":"{ \n\"initialDatetime\": \"2020-09-01\",\n\"finalDatetime\": \"2020-09-02\",\n \"allowStartingFromThePast\": false\n}","project":"Superalgos","id":"47fa4509-16f4-42b7-9453-fa3b3d2885b0","savedPayload":{"position":{"x":31715.41936714012,"y":28426.48024208079},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrame":{"type":"Time Frame","name":"New Time Frame","config":"{ \n\"label\": \"01-min\"\n}","project":"Superalgos","id":"dfe3514c-1aa9-4cea-bb2d-e6657037e69d","savedPayload":{"position":{"x":31804.686177549913,"y":28455.48478700282},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"slippage":{"type":"Slippage","name":"New Slippage","config":"{ \n\"marketOrderRate\": 0.1,\n\"stopLoss\": 0.2,\n\"takeProfit\": 0.3\n}","project":"Superalgos","id":"c711e510-373f-468d-8ed9-1601da6a06f5","savedPayload":{"position":{"x":31880.621061984013,"y":28510.654709903367},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"feeStructure":{"type":"Fee Structure","name":"New Fee Structure","config":"{ \n\"maker\": 0.1,\n\"taker\": 0.1\n}","project":"Superalgos","id":"fdc7c383-8301-4393-b415-8c2d542e05fe","savedPayload":{"position":{"x":31935.79098488456,"y":28586.589594337467},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"snapshots":{"type":"Snapshots","name":"New Snapshots","config":"{ \n\"strategy\": true,\n\"position\": true\n}","project":"Superalgos","id":"28db17c9-2703-430b-a162-5e04b68640a3","savedPayload":{"position":{"x":31964.79552980659,"y":28675.85640474726},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"heartbeats":{"type":"Heartbeats","name":"New Heartbeats","config":"{ \n\"date\": true,\n\"candleIndex\": false\n}","project":"Superalgos","id":"78270062-7d10-4afa-baee-2bda8a4b4ed2","savedPayload":{"position":{"x":31964.79552980659,"y":28769.7170837714},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"userDefinedParameters":{"type":"User Defined Parameters","name":"New User Defined Parameters","config":"{ \n\"param1Name\": \"A text string value example\",\n\"param2Name\": 0\n}","project":"Superalgos","id":"4c9cdc50-70c0-43ee-ad54-052f8b7ecbc8","savedPayload":{"position":{"x":31935.79098488456,"y":28858.983894181194},"targetPosition":{"x":31668.48902762805,"y":28722.78674425933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e79ab7df-ba40-46aa-abcd-63df8031a931","savedPayload":{"position":{"x":31668.48902762805,"y":28722.78674425933},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingSystemReference":{"type":"Trading System Reference","name":"Lightning Strike","project":"Superalgos","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2","savedPayload":{"position":{"x":31756.356993272086,"y":28934.918778615294},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},"tradingEngineReference":{"type":"Trading Engine Reference","name":"Low-Frequency","project":"Superalgos","id":"720feaab-efc8-435a-bb3c-ab4e33ed1ca2","savedPayload":{"position":{"x":31668.48902762805,"y":29147.050812971258},"targetPosition":{"x":31456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading Engine","name":"Low-Frequency","id":"eb20f622-71bf-4479-a574-d2320e1d4bd1"}}},"id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f","savedPayload":{"position":{"x":31456.356993272086,"y":28934.918778615294},"targetPosition":{"x":31156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"60a5e5c0-cfb3-4488-b46c-55d637212aa5","savedPayload":{"position":{"x":31156.356993272086,"y":28934.918778615294},"targetPosition":{"x":30856.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Trading","id":"a8c8d761-96e5-4a86-9285-6c3881d61442"}}}],"id":"cbfbb9e7-9c30-4482-8a9f-4c90771feffc","savedPayload":{"position":{"x":30856.356993272086,"y":28934.918778615294},"targetPosition":{"x":30556.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"08222935-2499-4a3e-a927-4f5dfbc392df","savedPayload":{"position":{"x":30556.356993272086,"y":28934.918778615294},"targetPosition":{"x":30256.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"56c5656b-a7e0-42ed-92d6-631e78ca99d0","savedPayload":{"position":{"x":30256.356993272086,"y":28934.918778615294},"targetPosition":{"x":29956.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1ce02342-473e-4614-ac76-c7788f56ab8e","savedPayload":{"position":{"x":29956.356993272086,"y":28934.918778615294},"targetPosition":{"x":29656.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"2db856e0-4719-408c-88bc-5b47d412c066","savedPayload":{"position":{"x":29656.356993272086,"y":28934.918778615294},"targetPosition":{"x":29356.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"ba36975c-08d6-458d-b7c0-eb4684a85b5d","savedPayload":{"position":{"x":29356.356993272086,"y":28934.918778615294},"targetPosition":{"x":29056.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"55c01047-3fce-41b3-9214-2e885f28b987","savedPayload":{"position":{"x":29056.356993272086,"y":28934.918778615294},"targetPosition":{"x":28756.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"8117db0a-e418-4f56-8fe4-fda2ddac1cbb","savedPayload":{"position":{"x":28756.356993272086,"y":28934.918778615294},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"productionTradingTasks":{"type":"Production Trading Tasks","name":"New Production Trading Tasks","project":"Superalgos","projectTradingTasks":[{"type":"Project Trading Tasks","name":"Superalgos","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binanceus","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binanceus BTC/USDT","project":"Superalgos","tradingMineTasks":[{"type":"Trading Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Lightning Strike","project":"Superalgos","bot":{"type":"Trading Bot Instance","name":"Low Frequency","config":"{}","project":"Superalgos","processes":[{"type":"Trading Process Instance","name":"Low Frequency Trading","project":"Superalgos","session":{"type":"Live Trading Session","name":"Lightning Strike","config":"{\"folderName\":\"Lightning-Strike\"}","project":"Superalgos","tradingParameters":{"type":"Trading Parameters","name":"New Parameters","project":"Superalgos","sessionBaseAsset":{"type":"Session Base Asset","name":"","config":"{\n\"initialBalance\": 0,\n\"minimumBalance\": 0\n}","project":"Superalgos","id":"5db563b5-a8d6-48c6-a34e-bbca8825ce37","savedPayload":{"position":{"x":27214.318791376507,"y":32665.54775609566},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"sessionQuotedAsset":{"type":"Session Quoted Asset","name":"","config":"{\n\"initialBalance\": 100\n}","project":"Superalgos","id":"f6cd46c1-66df-422c-82d4-02ac8e37f689","savedPayload":{"position":{"x":27314.957547074417,"y":32638.58168277913},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrame":{"type":"Time Frame","name":"New Time Frame","config":"{ \n\"label\": \"01-min\"\n}","project":"Superalgos","id":"727de4cc-40e6-4064-843c-8cb3a9f2fcdf","savedPayload":{"position":{"x":27418.749983429472,"y":32647.662344319935},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"slippage":{"type":"Slippage","name":"New Slippage","config":"{ \n\"marketOrderRate\": 0.1,\n\"stopLoss\": 0.2,\n\"takeProfit\": 0.3\n}","project":"Superalgos","id":"598dc355-73c9-4e7f-a0e9-ee5fd7952825","savedPayload":{"position":{"x":27513.177200804028,"y":32691.69447891996},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"feeStructure":{"type":"Fee Structure","name":"New Fee Structure","config":"{ \n\"maker\": 0.1,\n\"taker\": 0.1\n}","project":"Superalgos","id":"a3646bab-4d27-48a7-b17c-79d6da48f64d","savedPayload":{"position":{"x":27586.849883185412,"y":32765.367161301343},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"snapshots":{"type":"Snapshots","name":"New Snapshots","config":"{ \n\"strategy\": true,\n\"position\": true\n}","project":"Superalgos","id":"5021a926-442a-4341-8844-8a432293ecb1","savedPayload":{"position":{"x":27630.882017785436,"y":32859.7943786759},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"heartbeats":{"type":"Heartbeats","name":"New Heartbeats","config":"{ \n\"date\": true,\n\"candleIndex\": false\n}","project":"Superalgos","id":"e8cedec0-1bc2-46ba-98de-b7ff746a74c8","savedPayload":{"position":{"x":27639.96267932624,"y":32963.586815030954},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"userDefinedParameters":{"type":"User Defined Parameters","name":"New User Defined Parameters","config":"{ \n\"param1Name\": \"A text string value example\",\n\"param2Name\": 0\n}","project":"Superalgos","id":"67da1d57-62ff-424c-ab2e-034e008fc079","savedPayload":{"position":{"x":27612.99660600971,"y":33064.225570728864},"targetPosition":{"x":27341.104269898715,"y":32937.440092206656},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"726c35b1-e30b-4620-819f-a88a955f1902","savedPayload":{"position":{"x":27341.104269898715,"y":32937.440092206656},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingSystemReference":{"type":"Trading System Reference","name":"Lightning Strike","project":"Superalgos","id":"ff1cd7c1-9415-4c49-8ecf-188fd0c60ea4","savedPayload":{"position":{"x":27428.97223554275,"y":33149.57212656262},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},"tradingEngineReference":{"type":"Trading Engine Reference","name":"Low-Frequency","project":"Superalgos","id":"5fd0a826-0819-4f19-a999-66cc64be0272","savedPayload":{"position":{"x":27341.104269898715,"y":33361.70416091858},"targetPosition":{"x":27128.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Trading Engine","name":"Low-Frequency","id":"eb20f622-71bf-4479-a574-d2320e1d4bd1"}}},"id":"1ce123af-467f-4295-b317-dba8729faf25","savedPayload":{"position":{"x":27128.97223554275,"y":33149.57212656262},"targetPosition":{"x":26828.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Resistances and Supports Multi-Period-Daily","project":"Superalgos","id":"0d54601b-fcac-42c9-8ce6-d532bfc81de5","savedPayload":{"position":{"x":26978.97223554275,"y":33409.37974769795},"targetPosition":{"x":26828.97223554275,"y":33149.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"7e2fdde9-8b64-44a3-85f1-10c3935bd3e3"}}},"id":"4d7e7fa0-afcb-4b2f-983b-ceacea91b29d","savedPayload":{"position":{"x":26828.97223554275,"y":33149.57212656262},"targetPosition":{"x":26569.16461440742,"y":32999.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Trading","id":"a8c8d761-96e5-4a86-9285-6c3881d61442"}}}],"id":"2451fc98-0396-44df-902c-a3eaa90f0618","savedPayload":{"position":{"x":26569.16461440742,"y":32999.57212656262},"targetPosition":{"x":26309.356993272086,"y":32849.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"keyReference":{"type":"Key Reference","name":"Key for Lighting Strike","project":"Superalgos","id":"a0622fc9-c4e3-44c3-963d-7ae5fa163e99","savedPayload":{"position":{"x":26309.356993272086,"y":33149.57212656262},"targetPosition":{"x":26309.356993272086,"y":32849.57212656262},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Exchange Account Key","name":"Key for Lighting Strike","id":"e85bbbd6-aca8-450f-9237-788062de5761"}}},"id":"c8492c4a-a7a7-4a80-a25a-a610377e6180","savedPayload":{"position":{"x":26309.356993272086,"y":32849.57212656262},"targetPosition":{"x":26159.356993272086,"y":32589.76450542729},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"dd73b670-11d7-4cdc-848b-c063fb7a3848","savedPayload":{"position":{"x":26159.356993272086,"y":32589.76450542729},"targetPosition":{"x":26009.356993272086,"y":32329.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1e087225-153c-4c7e-b9ec-2a36f32ee511","savedPayload":{"position":{"x":26009.356993272086,"y":32329.956884291958},"targetPosition":{"x":25859.356993272086,"y":32070.149263156625},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"013985a8-7bf7-4b91-8e2d-f4e8bd81cb62","savedPayload":{"position":{"x":25859.356993272086,"y":32070.149263156625},"targetPosition":{"x":25709.356993272086,"y":31810.341642021293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"d539c0ac-aaeb-4c44-9dba-ac26df819a8d","savedPayload":{"position":{"x":25709.356993272086,"y":31810.341642021293},"targetPosition":{"x":25559.356993272086,"y":31550.53402088596},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"f4fc305a-6764-427e-86a7-6557118a4b35","savedPayload":{"position":{"x":25559.356993272086,"y":31550.53402088596},"targetPosition":{"x":25409.356993272086,"y":31290.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"673caa5f-511d-4688-9305-e5f0f0f780cd","savedPayload":{"position":{"x":28606.356993272086,"y":29194.726399750627},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataStorage":{"type":"Data Storage","name":"New Data Storage","project":"Superalgos","dataMinesData":{"type":"Data Mines Data","name":"New Data Mines Data","project":"Superalgos","projectDataProducts":[{"type":"Project Data Products","name":"Superalgos","project":"Superalgos","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binanceus","project":"Superalgos","marketDataProducts":[{"type":"Market Data Products","name":"Binanceus BTC/USDT","project":"Superalgos","dataProducts":[],"dataMineProducts":[{"type":"Data Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Candles Volumes","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Candles","project":"Superalgos","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab","savedPayload":{"position":{"x":25635.373168930517,"y":32126.257878002114},"targetPosition":{"x":25538.373168930517,"y":32224.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","project":"Superalgos","id":"07c11481-7dbd-477d-8bf7-79212542a6aa","savedPayload":{"position":{"x":25617.373168930517,"y":32183.257878002114},"targetPosition":{"x":25538.373168930517,"y":32224.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}}],"dataProductFolders":[],"id":"73bb62ff-8212-4387-b160-40ee8de2a133","savedPayload":{"position":{"x":28609.517851064033,"y":30737.271265196097},"targetPosition":{"x":28332.353991310647,"y":30622.46623548657},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Resistances and Supports","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Resistances","project":"Superalgos","id":"a1669770-1bbe-40f7-acb3-ded15272935f","savedPayload":{"position":{"x":25621.373168930517,"y":32076.257878002114},"targetPosition":{"x":25592.373168930517,"y":32158.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Resistances","id":"7a734501-a0fb-4305-803e-7e95d477c513"}}},{"type":"Data Product","name":"Supports","project":"Superalgos","id":"64899503-b618-493a-ba94-bfad2051a611","savedPayload":{"position":{"x":25644.373168930517,"y":32138.257878002114},"targetPosition":{"x":25592.373168930517,"y":32158.257878002114},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Supports","id":"bc3c43de-6312-47d4-ae3d-0c95c1b039e0"}}}],"dataProductFolders":[],"id":"a1855a09-0948-43de-bba7-8900c5c161d8","savedPayload":{"position":{"x":28371.51184897666,"y":30919.89969389871},"targetPosition":{"x":28332.353991310647,"y":30622.46623548657},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0","savedPayload":{"position":{"x":28332.353991310647,"y":30622.46623548657},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Products","name":"Sparta","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Simple Moving Average (SMA)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Popular SMAs","project":"Superalgos","id":"1b8ea542-14d1-42c0-9af9-c429c308c6fd","savedPayload":{"position":{"x":28043.567704942016,"y":30688.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Popular SMAs","id":"4029d5bf-a8ad-4d80-b874-2af506e0ab34"}}},{"type":"Data Product","name":"Base7 SMAs","project":"Superalgos","id":"589f977c-a9d4-446c-8b5e-ff54250d3b3a","savedPayload":{"position":{"x":28038.567704942016,"y":30670.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base7 SMAs","id":"a03ef0ea-5be9-4d40-952e-24789e77dbb6"}}},{"type":"Data Product","name":"Base11 SMAs","project":"Superalgos","id":"e582bbcc-1d03-4645-8320-acc12afd08cf","savedPayload":{"position":{"x":28120.567704942016,"y":30666.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base11 SMAs","id":"05fabbf9-7798-4a53-995e-53ae74bef3de"}}},{"type":"Data Product","name":"Base5 SMAs","project":"Superalgos","id":"53fe6df8-67cb-4c21-983d-875ea9b532db","savedPayload":{"position":{"x":28117.567704942016,"y":30709.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base5 SMAs","id":"2dcb55de-1673-409e-aa52-f51e7c7f8fa3"}}},{"type":"Data Product","name":"Base6 SMAs","project":"Superalgos","id":"eaaf75ea-2937-460f-87ee-990e632d6475","savedPayload":{"position":{"x":28135.567704942016,"y":30655.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base6 SMAs","id":"4ae22e54-cd02-4e2e-b638-1c5ea9a171ac"}}},{"type":"Data Product","name":"Base12 SMAs","project":"Superalgos","id":"8637a545-6fef-404b-b14f-8f4d11704e57","savedPayload":{"position":{"x":28181.567704942016,"y":30549.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base12 SMAs","id":"723d28e9-a010-48c5-bda0-43a4c2343ddf"}}},{"type":"Data Product","name":"Base30 SMAs","project":"Superalgos","id":"0ce01d0f-adf0-4fe5-961d-037ca8721a97","savedPayload":{"position":{"x":28223.567704942016,"y":30691.89369181134},"targetPosition":{"x":28135.567704942016,"y":30616.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Base30 SMAs","id":"607ebabd-9602-4e5c-803d-d4207dbd6794"}}}],"dataProductFolders":[],"id":"f6551bb8-06bd-4873-80b4-d233142c385b","savedPayload":{"position":{"x":28293.196133644633,"y":30919.89969389871},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Moving Average Convergence Diveregence (MACD)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"MACD 122609","project":"Superalgos","id":"9bc1f567-146e-474e-a12d-942e1f8b8876","savedPayload":{"position":{"x":27977.567704942016,"y":30613.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 122609","id":"6c0c9bf0-90af-4497-b4fb-49b5872b1119"}}},{"type":"Data Product","name":"MACD 031016","project":"Superalgos","id":"e8b6b822-9b76-4559-aefc-957751616417","savedPayload":{"position":{"x":28066.567704942016,"y":30615.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 031016","id":"d1482dc0-e9f1-47ba-b75e-961fa914a53a"}}},{"type":"Data Product","name":"MACD 081709","project":"Superalgos","id":"951914c1-dded-4dda-9f38-c5cc3359c4c0","savedPayload":{"position":{"x":28099.567704942016,"y":30629.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 081709","id":"683e6b29-9f82-4a8e-93eb-20ac0e81a750"}}},{"type":"Data Product","name":"MACD 245209","project":"Superalgos","id":"db2799ed-9bbc-4ba7-87b8-a33efbd513ba","savedPayload":{"position":{"x":28090.567704942016,"y":30512.89369181134},"targetPosition":{"x":28040.567704942016,"y":30604.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"MACD 245209","id":"47984765-8180-45cf-a9eb-f0a8b22d165d"}}}],"dataProductFolders":[],"id":"bdee55fc-b907-4378-acba-bd7795cfb8a0","savedPayload":{"position":{"x":28071.409847276,"y":30979.327150223482},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Products","name":"Relative Strenght Index (RSI)","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"RSI14","project":"Superalgos","id":"9c42c985-a07d-4892-8853-636d8fec20a0","savedPayload":{"position":{"x":28059.567704942016,"y":30670.89369181134},"targetPosition":{"x":28114.567704942016,"y":30712.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"RSI14","id":"e24248b9-90df-4b26-b5cc-0bac80efa0c7"}}}],"dataProductFolders":[],"id":"3b96186a-c4b9-4409-bf16-2ba82ec6d37c","savedPayload":{"position":{"x":27872.561702854644,"y":30864.522120513957},"targetPosition":{"x":28110.567704942016,"y":30681.89369181134},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"4e954d81-88ad-44b4-9ddf-5930e50d367e","savedPayload":{"position":{"x":28110.567704942016,"y":30681.89369181134},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Products","name":"Alpha","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Stochastic","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Stoch-14-3-3","project":"Superalgos","id":"0ac3f528-2409-45ae-9654-e7dbfd3dbb98","savedPayload":{"position":{"x":27900.719560520658,"y":30610.088662101814},"targetPosition":{"x":27845.719560520658,"y":30534.088662101814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stoch-14-3-3","id":"393dc97b-76ee-409a-9b8f-f264ed652b0b"}}}],"dataProductFolders":[],"id":"8bf2e1e4-cb46-4216-8393-2a6124f3f1f2","savedPayload":{"position":{"x":27673.713558433286,"y":30749.71709080443},"targetPosition":{"x":27911.719560520658,"y":30567.088662101814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"44ad7330-2754-433c-85e7-67bac01affb2","savedPayload":{"position":{"x":27911.719560520658,"y":30567.088662101814},"targetPosition":{"x":28149.72556260803,"y":30384.460233399197},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Alpha","id":"511bef1e-62d8-4ff9-8d87-15bd0d3d630c"}}}],"id":"6d7273da-5366-4fe3-9749-e643038abd7a","savedPayload":{"position":{"x":28149.72556260803,"y":30384.460233399197},"targetPosition":{"x":28188.883420274044,"y":30087.026774987055},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"9bc0aea4-0596-449c-91bd-4fb4cb672aa8","savedPayload":{"position":{"x":28188.883420274044,"y":30087.026774987055},"targetPosition":{"x":28228.041277940058,"y":29789.593316574912},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"db554581-93fa-465d-89f7-50f026e839d8","savedPayload":{"position":{"x":28228.041277940058,"y":29789.593316574912},"targetPosition":{"x":28267.19913560607,"y":29492.15985816277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"32e7c122-fa5a-4d00-9d71-d54e890e32de","savedPayload":{"position":{"x":28267.19913560607,"y":29492.15985816277},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"tradingMinesData":{"type":"Trading Mines Data","name":"New Trading Mines Data","project":"Superalgos","projectTradingProducts":[{"type":"Project Trading Products","name":"Superalgos","project":"Superalgos","exchangeTradingProducts":[{"type":"Exchange Trading Products","name":"Binanceus","project":"Superalgos","marketTradingProducts":[{"type":"Market Trading Products","name":"Binanceus BTC/USDT","project":"Superalgos","tradingSessionReferences":[{"type":"Trading Session Reference","name":"Lightning Strike Backtesting Session","project":"Superalgos","dataProducts":[],"tradingMineProducts":[{"type":"Trading Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Low Frequency","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Engine","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Episode","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading Episode Counters","project":"Superalgos","id":"a01b42b0-ea87-47ab-b0e9-52d4b10cb631","savedPayload":{"position":{"x":24463.592002018682,"y":31980.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Counters","id":"d81c6019-864e-42f5-94ba-2f249b865f85"}}},{"type":"Data Product","name":"Trading Episode Statistics","project":"Superalgos","id":"559a20a7-6697-4245-9d6c-ad7c0e31ff84","savedPayload":{"position":{"x":24313.592002018682,"y":31909.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Statistics","id":"400c7f49-37da-41fb-b83d-879960aa74ff"}}},{"type":"Data Product","name":"Episode Candle","project":"Superalgos","id":"24fab05f-ff78-4cca-af61-d4d0bb2f2960","savedPayload":{"position":{"x":24420.592002018682,"y":31952.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Candle","id":"b9a58113-cf27-4d57-9810-87a2cc158804"}}},{"type":"Data Product","name":"Episode Balances","project":"Superalgos","id":"7c580919-08ce-4aff-9e84-888fdf07caec","savedPayload":{"position":{"x":24281.592002018682,"y":31964.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Balances","id":"a9a53d82-133b-4417-b639-f9a56d338233"}}},{"type":"Data Product","name":"Distance To Trading Event","project":"Superalgos","id":"389797d4-8456-4258-9adf-246a6ba69016","savedPayload":{"position":{"x":24441.592002018682,"y":31984.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Distance To Trading Event","id":"8ea88d6c-7d7f-4152-b781-ea108df52c63"}}},{"type":"Data Product","name":"Episode Base Asset","project":"Superalgos","id":"323c7b0b-42b1-4ff0-9d4b-36c2fd605caa","savedPayload":{"position":{"x":24417.592002018682,"y":31995.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Base Asset","id":"234969ff-eab1-4d59-b6fa-79433c9a20e9"}}},{"type":"Data Product","name":"Episode Quoted Asset","project":"Superalgos","id":"63594fc6-3b89-4507-bca8-2d43ef618cbe","savedPayload":{"position":{"x":24475.592002018682,"y":31901.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Quoted Asset","id":"ae525e31-d6a8-47d2-9021-3f2ddb9615b0"}}},{"type":"Data Product","name":"Current Episode","project":"Superalgos","id":"73bb3f9e-b112-4e5a-bce9-6d4bec41cc6c","savedPayload":{"position":{"x":24306.592002018682,"y":32068.531877463392},"targetPosition":{"x":24377.592002018682,"y":31972.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Episode","id":"b8da0132-ba28-46ec-aa54-eb9eaac56ce7"}}}],"dataProductFolders":[],"id":"a606455e-f5ce-4535-b1af-6d9dd529f91c","savedPayload":{"position":{"x":24377.592002018682,"y":31972.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Strategy","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Strategy","project":"Superalgos","id":"515f5fd6-d860-44d4-b5d6-a19acd9c5c86","savedPayload":{"position":{"x":24475.592002018682,"y":31953.531877463392},"targetPosition":{"x":24454.592002018682,"y":32022.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Strategy","id":"895d8a04-ef45-41a7-909a-ba31013ffb90"}}},{"type":"Data Product","name":"Last Strategy","project":"Superalgos","id":"556e97e8-eba3-419d-869d-950cc99371da","savedPayload":{"position":{"x":24448.592002018682,"y":32071.531877463392},"targetPosition":{"x":24454.592002018682,"y":32022.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Strategy","id":"0625f524-2b97-4b4d-8a90-590ffc62ecd3"}}}],"dataProductFolders":[],"id":"3af0887b-ae23-4f57-b376-4a540fe13112","savedPayload":{"position":{"x":24454.592002018682,"y":32022.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Position","project":"Superalgos","id":"d33abc39-702b-4d7a-8435-43d90e0f2c3a","savedPayload":{"position":{"x":24352.592002018682,"y":32024.531877463392},"targetPosition":{"x":24447.592002018682,"y":32101.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Position","id":"832ecada-8da3-4ba6-b6e9-be34dd5f7ce9"}}},{"type":"Data Product","name":"Last Position","project":"Superalgos","id":"d681fd5f-64af-4f39-9f6d-a767bef7692f","savedPayload":{"position":{"x":24398.592002018682,"y":32035.531877463392},"targetPosition":{"x":24447.592002018682,"y":32101.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Position","id":"477cd6d5-862a-44d0-9313-786a4e63a602"}}}],"dataProductFolders":[],"id":"895feaf2-ae82-4b8e-ada6-780beab73ea9","savedPayload":{"position":{"x":24447.592002018682,"y":32101.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Open Stage","project":"Superalgos","id":"b0961496-1af9-48cd-bbeb-ac5973192e78","savedPayload":{"position":{"x":24555.592002018682,"y":31897.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stage","id":"73c3c041-ba2a-4798-a362-a453409b518a"}}},{"type":"Data Product","name":"Close Stage","project":"Superalgos","id":"0c9cf78d-ce6e-4318-811d-e748ca72845d","savedPayload":{"position":{"x":24541.592002018682,"y":31929.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stage","id":"2bb9bb41-1ff5-4f83-aa5b-bfc4c9f06a9a"}}},{"type":"Data Product","name":"Trigger Stage","project":"Superalgos","id":"e298787f-b7f2-4334-931e-38b9441e43f9","savedPayload":{"position":{"x":24504.592002018682,"y":31961.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stage","id":"b6cff826-9056-4fbd-8eca-cbd6cceec962"}}},{"type":"Data Product","name":"Manage Stage","project":"Superalgos","id":"4719b69d-b23e-4037-8c0a-b641fd8ab14c","savedPayload":{"position":{"x":24444.592002018682,"y":31908.531877463392},"targetPosition":{"x":24520.592002018682,"y":31974.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stage","id":"bd691611-e7a6-49a8-b07d-c15360b55e40"}}}],"dataProductFolders":[],"id":"9fe11205-286a-4610-81ec-29cbc70d6075","savedPayload":{"position":{"x":24520.592002018682,"y":31974.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"90834a1b-cc7e-48a9-be5c-0e30380af4bd","savedPayload":{"position":{"x":24483.592002018682,"y":31990.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"7c769317-2639-4460-8b88-9dc92f7b0585"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"e2112d60-5fc2-4e67-befe-d4fbd6c1de77","savedPayload":{"position":{"x":24491.592002018682,"y":32003.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"9cc7645a-54fe-40d6-9896-9278167011fb"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"e734b6be-ba40-468c-a94f-1153dc85e00c","savedPayload":{"position":{"x":24445.592002018682,"y":32089.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"4c827ee0-a29b-4b65-8438-03e2ea98b410"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"9a973229-4d9d-45af-b5aa-64906a915f6e","savedPayload":{"position":{"x":24422.592002018682,"y":32032.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2c753cd8-36d8-466c-bd80-1ebfa8e314dc"}}},{"type":"Data Product","name":"Last Market Order","project":"Superalgos","id":"56517fe9-64da-4404-83f3-005106bc1c0a","savedPayload":{"position":{"x":24412.592002018682,"y":32018.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Market Order","id":"6df1ac87-92d5-4788-b0bc-f3543b283ef0"}}},{"type":"Data Product","name":"Last Limit Order","project":"Superalgos","id":"d00c76e7-4be0-4518-9892-a0f6df943951","savedPayload":{"position":{"x":24594.592002018682,"y":31949.531877463392},"targetPosition":{"x":24511.592002018682,"y":32023.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Limit Order","id":"c24ec6a1-e937-4d20-93eb-4faf2a0becc3"}}}],"dataProductFolders":[],"id":"b5154bc1-4311-4148-b396-5ebca1c62417","savedPayload":{"position":{"x":24511.592002018682,"y":32023.531877463392},"targetPosition":{"x":24421.592002018682,"y":32058.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"89edd698-1d64-4500-bcef-d13ea74bee1c","savedPayload":{"position":{"x":24421.592002018682,"y":32058.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Trading System","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading System Errors","project":"Superalgos","id":"a0c29c57-0a20-4084-9697-142300f62f9c","savedPayload":{"position":{"x":24383.592002018682,"y":32063.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Errors","id":"1d9c570d-77c7-40ac-a61e-c5a57a411de8"}}},{"type":"Data Product","name":"Trading System Highlights","project":"Superalgos","id":"aa0fe882-89a8-4811-8988-c589554afe9d","savedPayload":{"position":{"x":24294.592002018682,"y":32008.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Highlights","id":"319f660a-78be-4cf4-8052-877837cad806"}}},{"type":"Data Product","name":"Trading System Values","project":"Superalgos","id":"bbc65054-b22b-4cbb-816b-529672e2f498","savedPayload":{"position":{"x":24324.592002018682,"y":32032.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Values","id":"c90c009b-588d-45d4-aff1-05e375181dfa"}}},{"type":"Data Product","name":"Trading System Status","project":"Superalgos","id":"776a3ece-8255-4e80-b60f-85bb818b561f","savedPayload":{"position":{"x":24340.592002018682,"y":32026.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Status","id":"eed48c80-35c5-49fa-b12d-18e7280ffb8f"}}},{"type":"Data Product","name":"Trading System Progress","project":"Superalgos","id":"7593aaf9-0505-4b58-9920-235340ff2d2f","savedPayload":{"position":{"x":24325.592002018682,"y":32003.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Progress","id":"04c8606b-5e59-4e7d-b3ac-387bfffcd300"}}},{"type":"Data Product","name":"Trading System Running","project":"Superalgos","id":"3e2e6105-f41f-42e2-bce5-74ebb3b81cbd","savedPayload":{"position":{"x":24332.592002018682,"y":32039.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Running","id":"17236f59-6ef2-4cc3-913c-1ff6db052236"}}},{"type":"Data Product","name":"Trading System Announcements","project":"Superalgos","id":"faab4399-898b-4393-8c27-fa2f3109c60a","savedPayload":{"position":{"x":24307.592002018682,"y":32057.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Announcements","id":"4a6f828a-9671-431e-8257-fc920943581e"}}},{"type":"Data Product","name":"Trading System Warnings","project":"Superalgos","id":"9ff0f035-ca7f-4e65-a82c-186fa7f09157","savedPayload":{"position":{"x":24297.592002018682,"y":32133.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Warnings","id":"34310596-466a-4e9a-a5a2-256b0fe3e339"}}},{"type":"Data Product","name":"Trading System Infos","project":"Superalgos","id":"04210a59-070a-45f1-a2a0-cf50bd4879f7","savedPayload":{"position":{"x":24389.592002018682,"y":31999.531877463392},"targetPosition":{"x":24378.592002018682,"y":32060.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Infos","id":"020ad519-0fc6-4f2f-9f26-b2c7de118fb8"}}}],"dataProductFolders":[],"id":"1a16bc12-581d-4626-846c-895f08e65fdf","savedPayload":{"position":{"x":24378.592002018682,"y":32060.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Objects","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Episodes","project":"Superalgos","id":"73dff61a-7b05-4ca6-b963-99d6c578e9ba","savedPayload":{"position":{"x":24433.592002018682,"y":31946.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episodes","id":"aeec080e-8caf-4976-8187-ba4e725b73b0"}}},{"type":"Data Product","name":"Strategies","project":"Superalgos","id":"a9c454c8-9075-4dcf-bfe9-ebd0c1658049","savedPayload":{"position":{"x":24490.592002018682,"y":31966.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Strategies","id":"21db6fce-8450-4b07-9015-d81a339fd030"}}}],"dataProductFolders":[{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"cad1eecc-e897-4086-b42c-fcfd843c04cc","savedPayload":{"position":{"x":24570.592002018682,"y":32052.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"db256083-9aa2-48e1-8fd6-3425a5085302"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"fdf22e85-7071-4847-bdba-e3fb43a616ed","savedPayload":{"position":{"x":24567.592002018682,"y":32057.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"1958f79b-5c6c-4874-9154-98c314822ed7"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"d2b1ab31-d8a1-422b-a717-33ee7df9b07b","savedPayload":{"position":{"x":24545.592002018682,"y":31956.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"5deceb32-c7ab-4560-818a-0f0b9d6632fb"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"3b5a12db-b969-4400-8b9d-afb9b7b81642","savedPayload":{"position":{"x":24672.592002018682,"y":31889.531877463392},"targetPosition":{"x":24586.592002018682,"y":31971.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2a1d405b-2fbe-4ed4-a76a-d2c7be59d20e"}}}],"dataProductFolders":[],"id":"97736b8e-761c-43f2-83bf-df8f5d41b963","savedPayload":{"position":{"x":24586.592002018682,"y":31971.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trigger Stages","project":"Superalgos","id":"9fc29be1-9393-4933-95d3-bebddd73c05e","savedPayload":{"position":{"x":24507.592002018682,"y":31875.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stages","id":"18cc2e79-7e57-418c-b635-6c68fc11d681"}}},{"type":"Data Product","name":"Open Stages","project":"Superalgos","id":"b555388f-db93-4db1-91be-7772550afa70","savedPayload":{"position":{"x":24439.592002018682,"y":31926.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stages","id":"d5938c00-0849-466d-ae14-4ea91b571678"}}},{"type":"Data Product","name":"Manage Stages","project":"Superalgos","id":"41953904-e48c-4176-bf0f-09d133bc444c","savedPayload":{"position":{"x":24441.592002018682,"y":31883.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stages","id":"8fab86b3-db8d-4113-8418-1d256bd98cf2"}}},{"type":"Data Product","name":"Close Stages","project":"Superalgos","id":"47b4553c-7f2e-438c-9f4b-9ba30e943a6c","savedPayload":{"position":{"x":24463.592002018682,"y":31931.531877463392},"targetPosition":{"x":24487.592002018682,"y":31875.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stages","id":"ba911e61-f951-48cd-b547-9a70aa211100"}}}],"dataProductFolders":[],"id":"ac789224-64dc-4ff5-a316-2dfbb6347b8a","savedPayload":{"position":{"x":24487.592002018682,"y":31875.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Positions","project":"Superalgos","id":"6e49b57f-8c94-410f-985b-82c126155b11","savedPayload":{"position":{"x":24693.592002018682,"y":31870.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Positions","id":"1eabba24-cbd4-4cbf-95e0-c5135349d41d"}}},{"type":"Data Product","name":"Position Base Asset","project":"Superalgos","id":"ae8fa9a5-95b6-4769-8ade-f9854e6855ba","savedPayload":{"position":{"x":24673.592002018682,"y":32018.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Base Asset","id":"b371b039-f6c8-4f60-84cb-52f55c96c84d"}}},{"type":"Data Product","name":"Position Quoted Asset","project":"Superalgos","id":"9e9b19ee-9c51-4586-b74d-d2880f13f71f","savedPayload":{"position":{"x":24656.592002018682,"y":31987.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Quoted Asset","id":"a376f02b-a5d2-4079-b5cd-ab7dc894b909"}}},{"type":"Data Product","name":"Stop Loss","project":"Superalgos","id":"01491591-0462-453c-91e0-6da6f554a729","savedPayload":{"position":{"x":24536.592002018682,"y":31883.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stop Loss","id":"c18bdc82-216a-4b1d-8850-5c3c9dc2000b"}}},{"type":"Data Product","name":"Take Profit","project":"Superalgos","id":"719dd8a6-58ab-41c6-9693-9b67c12232d2","savedPayload":{"position":{"x":24558.592002018682,"y":31830.531877463392},"targetPosition":{"x":24616.592002018682,"y":31921.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Take Profit","id":"2542c7d0-fa26-4b52-a59a-a3630e52eb89"}}}],"dataProductFolders":[],"id":"2a4cb5a2-8e6a-4b14-816a-b8e0cce4dae5","savedPayload":{"position":{"x":24616.592002018682,"y":31921.531877463392},"targetPosition":{"x":24528.592002018682,"y":31946.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"39e122ca-cdc4-49a6-91a6-2f2c05f62ea0","savedPayload":{"position":{"x":24528.592002018682,"y":31946.531877463392},"targetPosition":{"x":24436.592002018682,"y":31978.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"363150a9-d4e7-4e2e-b327-89109935718c","savedPayload":{"position":{"x":24436.592002018682,"y":31978.531877463392},"targetPosition":{"x":24383.592002018682,"y":32012.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7","savedPayload":{"position":{"x":24383.592002018682,"y":32012.531877463392},"targetPosition":{"x":24343.592002018682,"y":31925.531877463392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"a5de30a4-022e-4f8a-afd0-3eb6d8600ae8","savedPayload":{"position":{"x":27706.356993272086,"y":30533.956884291958},"targetPosition":{"x":27706.356993272086,"y":30233.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Trading Session Reference","name":"Lightning Strike Live Trading Session","project":"Superalgos","dataProducts":[],"tradingMineProducts":[{"type":"Trading Mine Products","name":"Masters","project":"Superalgos","botProducts":[{"type":"Bot Products","name":"Low Frequency","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Engine","project":"Superalgos","dataProducts":[],"dataProductFolders":[{"type":"Data Product Folder","name":"Trading Episode","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading Episode Counters","project":"Superalgos","id":"dc6cc4ef-4bd7-4837-8442-919462314db3","savedPayload":{"position":{"x":24040.07658106541,"y":32774.458634291004},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Counters","id":"d81c6019-864e-42f5-94ba-2f249b865f85"}}},{"type":"Data Product","name":"Trading Episode Statistics","project":"Superalgos","id":"776ed571-8321-47aa-8cfb-c8ebf565dace","savedPayload":{"position":{"x":24033.260548494378,"y":32904.51628344689},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading Episode Statistics","id":"400c7f49-37da-41fb-b83d-879960aa74ff"}}},{"type":"Data Product","name":"Episode Candle","project":"Superalgos","id":"ded93703-a48d-44be-9703-878c28f949cd","savedPayload":{"position":{"x":23982.373237179447,"y":33024.39927619857},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Candle","id":"b9a58113-cf27-4d57-9810-87a2cc158804"}}},{"type":"Data Product","name":"Episode Balances","project":"Superalgos","id":"e702f1dd-1c91-4d05-ac55-19db363f5f3a","savedPayload":{"position":{"x":23893.552407881933,"y":33119.64795433567},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Balances","id":"a9a53d82-133b-4417-b639-f9a56d338233"}}},{"type":"Data Product","name":"Distance To Trading Event","project":"Superalgos","id":"b8abea53-8221-47bd-91a2-cdcdd2ad1027","savedPayload":{"position":{"x":23777.51116347094,"y":33178.77392155408},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Distance To Trading Event","id":"8ea88d6c-7d7f-4152-b781-ea108df52c63"}}},{"type":"Data Product","name":"Episode Base Asset","project":"Superalgos","id":"18bcbd26-c237-4acb-96f4-d9c95d833a42","savedPayload":{"position":{"x":23648.24579060881,"y":33194.6457136009},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Base Asset","id":"234969ff-eab1-4d59-b6fa-79433c9a20e9"}}},{"type":"Data Product","name":"Episode Quoted Asset","project":"Superalgos","id":"c444f4b5-fa67-4c21-afa8-1f998da7a2a2","savedPayload":{"position":{"x":23521.347601016434,"y":33165.348958112605},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episode Quoted Asset","id":"ae525e31-d6a8-47d2-9021-3f2ddb9615b0"}}},{"type":"Data Product","name":"Current Episode","project":"Superalgos","id":"057570bd-69d4-4f3c-b0d4-94ee32f61e65","savedPayload":{"position":{"x":23412.122389176475,"y":33094.417276175125},"targetPosition":{"x":23667.871774199913,"y":32820.15963806794},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Episode","id":"b8da0132-ba28-46ec-aa54-eb9eaac56ce7"}}}],"dataProductFolders":[],"id":"6a331de0-7872-4f86-bea0-6dd802c97921","savedPayload":{"position":{"x":23667.871774199913,"y":32820.15963806794},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Strategy","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Strategy","project":"Superalgos","id":"88dd680c-a81b-48ae-96ba-838281abfa35","savedPayload":{"position":{"x":23648.24579060881,"y":33194.6457136009},"targetPosition":{"x":23477.99935320648,"y":32860.51826703026},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Strategy","id":"895d8a04-ef45-41a7-909a-ba31013ffb90"}}},{"type":"Data Product","name":"Last Strategy","project":"Superalgos","id":"24af3ffc-6a52-4ee3-a30b-f068aa5b2062","savedPayload":{"position":{"x":23273.759715075845,"y":33175.01973000979},"targetPosition":{"x":23477.99935320648,"y":32860.51826703026},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Strategy","id":"0625f524-2b97-4b4d-8a90-590ffc62ecd3"}}}],"dataProductFolders":[],"id":"74c10f36-887b-4233-81e5-abe365511bfa","savedPayload":{"position":{"x":23477.99935320648,"y":32860.51826703026},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Current Position","project":"Superalgos","id":"25280962-e4e5-40df-9e42-9edfbad6f6d3","savedPayload":{"position":{"x":23273.759715075845,"y":33175.01973000979},"targetPosition":{"x":23293.38569866695,"y":32800.533654476836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Current Position","id":"832ecada-8da3-4ba6-b6e9-be34dd5f7ce9"}}},{"type":"Data Product","name":"Last Position","project":"Superalgos","id":"7a95a249-132d-4e0f-9182-cc7af45cacea","savedPayload":{"position":{"x":22959.25825209631,"y":32970.78009187916},"targetPosition":{"x":23293.38569866695,"y":32800.533654476836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Position","id":"477cd6d5-862a-44d0-9313-786a4e63a602"}}}],"dataProductFolders":[],"id":"7eca88a8-3724-4ca1-aa30-9227727eb834","savedPayload":{"position":{"x":23293.38569866695,"y":32800.533654476836},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Open Stage","project":"Superalgos","id":"c9c4bca7-f918-4aa8-b538-ffe8aa31d5c2","savedPayload":{"position":{"x":23104.83496583686,"y":33026.66175662281},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stage","id":"73c3c041-ba2a-4798-a362-a453409b518a"}}},{"type":"Data Product","name":"Close Stage","project":"Superalgos","id":"4201d7c0-43aa-4ac0-bd7e-ab26b688aa2d","savedPayload":{"position":{"x":22898.332847281992,"y":32921.44367184458},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stage","id":"2bb9bb41-1ff5-4f83-aa5b-bfc4c9f06a9a"}}},{"type":"Data Product","name":"Trigger Stage","project":"Superalgos","id":"4fe24ddc-973f-4a5d-bf8a-d77090486125","savedPayload":{"position":{"x":22793.11476250377,"y":32714.941553289715},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stage","id":"b6cff826-9056-4fbd-8eca-cbd6cceec962"}}},{"type":"Data Product","name":"Manage Stage","project":"Superalgos","id":"e2f3d69e-2f0a-4463-8e74-4f0768c4fb70","savedPayload":{"position":{"x":22829.37044365631,"y":32486.0321914973},"targetPosition":{"x":23163.497890226947,"y":32656.27862889963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stage","id":"bd691611-e7a6-49a8-b07d-c15360b55e40"}}}],"dataProductFolders":[],"id":"7236bd16-a6e3-48ac-89bf-dc8674b7e812","savedPayload":{"position":{"x":23163.497890226947,"y":32656.27862889963},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"0e0b284a-5014-4ab0-ada0-4322c14a099e","savedPayload":{"position":{"x":22942.973442347367,"y":32795.291108279984},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"7c769317-2639-4460-8b88-9dc92f7b0585"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"95b3db7a-9b62-4eab-a76b-4af8794da5a6","savedPayload":{"position":{"x":22818.117657046547,"y":32684.55024509317},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"9cc7645a-54fe-40d6-9896-9278167011fb"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"1c6eed42-23aa-4174-aade-be29222acb8c","savedPayload":{"position":{"x":22753.675141305597,"y":32530.603279980434},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"4c827ee0-a29b-4b65-8438-03e2ea98b410"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"a2f44cd5-090d-42e5-9eb7-73e732310e85","savedPayload":{"position":{"x":22762.409525702606,"y":32363.941297417976},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2c753cd8-36d8-466c-bd80-1ebfa8e314dc"}}},{"type":"Data Product","name":"Last Market Order","project":"Superalgos","id":"8c24d559-ba52-46fe-81b4-8a6bf50c74b6","savedPayload":{"position":{"x":22842.590858287545,"y":32217.573747027367},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Market Order","id":"6df1ac87-92d5-4788-b0bc-f3543b283ef0"}}},{"type":"Data Product","name":"Last Limit Order","project":"Superalgos","id":"c451c035-5ece-451f-836f-b5334cb3f967","savedPayload":{"position":{"x":22978.338242782465,"y":32120.49051724367},"targetPosition":{"x":23123.13926126462,"y":32466.406207906195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Last Limit Order","id":"c24ec6a1-e937-4d20-93eb-4faf2a0becc3"}}}],"dataProductFolders":[],"id":"ce9593a8-3e87-43bb-88c7-af50cf651806","savedPayload":{"position":{"x":23123.13926126462,"y":32466.406207906195},"targetPosition":{"x":23497.625336797584,"y":32486.0321914973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8be94a26-6821-48bb-8169-3eae2a1131af","savedPayload":{"position":{"x":23497.625336797584,"y":32486.0321914973},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Trading System","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trading System Errors","project":"Superalgos","id":"ba606f99-2ae5-44dc-b7db-399e657830e1","savedPayload":{"position":{"x":23295.861450927674,"y":32622.443323337528},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Errors","id":"1d9c570d-77c7-40ac-a61e-c5a57a411de8"}}},{"type":"Data Product","name":"Trading System Highlights","project":"Superalgos","id":"2d20d8ae-4afa-4e92-8de2-89e66e5efdee","savedPayload":{"position":{"x":23182.53338349962,"y":32592.0771591904},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Highlights","id":"319f660a-78be-4cf4-8052-877837cad806"}}},{"type":"Data Product","name":"Trading System Values","project":"Superalgos","id":"f8a6219c-c7b4-410a-8aa4-1910583f51c8","savedPayload":{"position":{"x":23084.13564726847,"y":32528.17692212845},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Values","id":"c90c009b-588d-45d4-aff1-05e375181dfa"}}},{"type":"Data Product","name":"Trading System Status","project":"Superalgos","id":"dcff6f56-7646-4505-aa93-6682a110f3f2","savedPayload":{"position":{"x":23010.300098233878,"y":32436.997612574425},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Status","id":"eed48c80-35c5-49fa-b12d-18e7280ffb8f"}}},{"type":"Data Product","name":"Trading System Progress","project":"Superalgos","id":"0a9dff80-e462-4110-b988-11ce57bbbcd5","savedPayload":{"position":{"x":22968.25427437787,"y":32327.464496631084},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Progress","id":"04c8606b-5e59-4e7d-b3ac-387bfffcd300"}}},{"type":"Data Product","name":"Trading System Running","project":"Superalgos","id":"c7e05ad0-7d4a-4ffb-9aee-191511f85ee7","savedPayload":{"position":{"x":22962.11391388994,"y":32210.299438849055},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Running","id":"17236f59-6ef2-4cc3-913c-1ff6db052236"}}},{"type":"Data Product","name":"Trading System Announcements","project":"Superalgos","id":"e4811789-fd94-49b0-9917-8d9d434f997d","savedPayload":{"position":{"x":22992.480078037068,"y":32096.971371421},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Announcements","id":"4a6f828a-9671-431e-8257-fc920943581e"}}},{"type":"Data Product","name":"Trading System Warnings","project":"Superalgos","id":"029ff3a7-9c65-425f-855a-882df68fa05b","savedPayload":{"position":{"x":23056.38031509902,"y":31998.573635189852},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Warnings","id":"34310596-466a-4e9a-a5a2-256b0fe3e339"}}},{"type":"Data Product","name":"Trading System Infos","project":"Superalgos","id":"0f47adaf-25a0-431f-b15b-0fbf44069b38","savedPayload":{"position":{"x":23147.559624653044,"y":31924.73808615526},"targetPosition":{"x":23335.059624653044,"y":32249.497612574425},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trading System Infos","id":"020ad519-0fc6-4f2f-9f26-b2c7de118fb8"}}}],"dataProductFolders":[],"id":"7096a712-deb7-4adb-86e0-d688f24d2832","savedPayload":{"position":{"x":23335.059624653044,"y":32249.497612574425},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Objects","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Episodes","project":"Superalgos","id":"c6fd6067-4b57-4860-ae3b-5668e4444490","savedPayload":{"position":{"x":23053.23606537805,"y":32137.53752778946},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Episodes","id":"aeec080e-8caf-4976-8187-ba4e725b73b0"}}},{"type":"Data Product","name":"Strategies","project":"Superalgos","id":"60f88096-7343-42d1-afad-83fecd22fb44","savedPayload":{"position":{"x":23012.87743641572,"y":31947.665106796027},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Strategies","id":"21db6fce-8450-4b07-9015-d81a339fd030"}}}],"dataProductFolders":[{"type":"Data Product Folder","name":"Orders","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Market Buy Orders","project":"Superalgos","id":"9f939086-c934-4924-8353-776707a7cf10","savedPayload":{"position":{"x":22722.769389032703,"y":31897.43943333598},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Buy Orders","id":"db256083-9aa2-48e1-8fd6-3425a5085302"}}},{"type":"Data Product","name":"Market Sell Orders","project":"Superalgos","id":"da5f279e-d387-43cf-80f4-fc114b9ac906","savedPayload":{"position":{"x":22710.63986411075,"y":31665.99431034305},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Market Sell Orders","id":"1958f79b-5c6c-4874-9154-98c314822ed7"}}},{"type":"Data Product","name":"Limit Buy Orders","project":"Superalgos","id":"367646bb-839a-4071-8305-6d26a647585d","savedPayload":{"position":{"x":22836.866902325462,"y":31471.62171671013},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Buy Orders","id":"5deceb32-c7ab-4560-818a-0f0b9d6632fb"}}},{"type":"Data Product","name":"Limit Sell Orders","project":"Superalgos","id":"0b2fc73a-9635-40b2-98d8-0c79c69175a9","savedPayload":{"position":{"x":23053.23606537805,"y":31388.56537672353},"targetPosition":{"x":23072.862048969153,"y":31763.051452256495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Limit Sell Orders","id":"2a1d405b-2fbe-4ed4-a76a-d2c7be59d20e"}}}],"dataProductFolders":[],"id":"88643ab2-7859-45d4-b967-8681cf970828","savedPayload":{"position":{"x":23072.862048969153,"y":31763.051452256495},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Stages","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Trigger Stages","project":"Superalgos","id":"7fe8c58f-9cad-47c9-ba4e-d66bff094dcf","savedPayload":{"position":{"x":22846.73394682318,"y":31574.500719426407},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Trigger Stages","id":"18cc2e79-7e57-418c-b635-6c68fc11d681"}}},{"type":"Data Product","name":"Open Stages","project":"Superalgos","id":"41f17745-1819-4681-8a2b-9bdda3cd67c4","savedPayload":{"position":{"x":22951.952031601402,"y":31367.99860087154},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Open Stages","id":"d5938c00-0849-466d-ae14-4ea91b571678"}}},{"type":"Data Product","name":"Manage Stages","project":"Superalgos","id":"e89c8bfd-fac9-4aff-afc0-3a89c1dc2710","savedPayload":{"position":{"x":23158.45415015627,"y":31262.780516093317},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Manage Stages","id":"8fab86b3-db8d-4113-8418-1d256bd98cf2"}}},{"type":"Data Product","name":"Close Stages","project":"Superalgos","id":"bc2c6503-e935-4ad7-a76a-89b062d41e91","savedPayload":{"position":{"x":23387.363511948686,"y":31299.036197245856},"targetPosition":{"x":23217.117074546357,"y":31633.163643816493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Close Stages","id":"ba911e61-f951-48cd-b547-9a70aa211100"}}}],"dataProductFolders":[],"id":"869369c1-13de-4086-ad40-77b3d54cfc36","savedPayload":{"position":{"x":23217.117074546357,"y":31633.163643816493},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Data Product Folder","name":"Position","project":"Superalgos","dataProducts":[{"type":"Data Product","name":"Positions","project":"Superalgos","id":"3ed594a0-8452-4bd8-9eaa-37cd83a45b90","savedPayload":{"position":{"x":23092.488032560257,"y":31388.56537672353},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Positions","id":"1eabba24-cbd4-4cbf-95e0-c5135349d41d"}}},{"type":"Data Product","name":"Position Base Asset","project":"Superalgos","id":"88997c97-e77f-490e-9eb5-c7531beec132","savedPayload":{"position":{"x":23236.74305813746,"y":31258.67756828353},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Base Asset","id":"b371b039-f6c8-4f60-84cb-52f55c96c84d"}}},{"type":"Data Product","name":"Position Quoted Asset","project":"Superalgos","id":"b4772611-d5d0-4fbd-b689-d42de3c045d4","savedPayload":{"position":{"x":23426.615479130895,"y":31218.3189393212},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Position Quoted Asset","id":"a376f02b-a5d2-4079-b5cd-ab7dc894b909"}}},{"type":"Data Product","name":"Stop Loss","project":"Superalgos","id":"9b064960-3829-441f-b955-334fb8324a53","savedPayload":{"position":{"x":23611.229133670426,"y":31278.303551874633},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Stop Loss","id":"c18bdc82-216a-4b1d-8850-5c3c9dc2000b"}}},{"type":"Data Product","name":"Take Profit","project":"Superalgos","id":"cbcc817b-4333-4c80-addc-e2a0ee0845c1","savedPayload":{"position":{"x":23741.116942110428,"y":31422.558577451837},"targetPosition":{"x":23406.98949553979,"y":31592.805014854166},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Take Profit","id":"2542c7d0-fa26-4b52-a59a-a3630e52eb89"}}}],"dataProductFolders":[],"id":"7f74f2e1-91b6-4d7a-87cb-1d6232a41876","savedPayload":{"position":{"x":23406.98949553979,"y":31592.805014854166},"targetPosition":{"x":23387.363511948686,"y":31967.29109038713},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"291949a0-847b-4b18-b3b4-191496fc38a9","savedPayload":{"position":{"x":23387.363511948686,"y":31967.29109038713},"targetPosition":{"x":23701.86497492822,"y":32171.530728517766},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ae78f4fc-6ee5-4ae4-9847-3bab0e2e51a6","savedPayload":{"position":{"x":23701.86497492822,"y":32171.530728517766},"targetPosition":{"x":24068.670325203395,"y":32093.563844461107},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"aa2b0766-a3d5-47e1-acd8-7345af564388","savedPayload":{"position":{"x":24068.670325203395,"y":32093.563844461107},"targetPosition":{"x":24313.207225386846,"y":32041.58592175667},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Trading Mine","name":"Masters","id":"6a54eece-4582-4cda-a854-1cd805e00fed"}}}],"id":"9ef30086-0c9d-47c2-8983-db5fc9a99583","savedPayload":{"position":{"x":27446.549372136753,"y":30383.956884291958},"targetPosition":{"x":27706.356993272086,"y":30233.956884291958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Live Trading Session","name":"Lightning Strike","id":"1ce123af-467f-4295-b317-dba8729faf25"}}}],"id":"026bab29-64d0-4d83-862c-446657efa101","savedPayload":{"position":{"x":27706.356993272086,"y":30233.956884291958},"targetPosition":{"x":27856.356993272086,"y":29974.149263156625},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"f601d2a7-fada-477f-9b63-3ef7ed42d44a","savedPayload":{"position":{"x":27856.356993272086,"y":29974.149263156625},"targetPosition":{"x":28006.356993272086,"y":29714.341642021293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binanceus","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"691abc38-257f-462f-bee5-1cc51d77cea6","savedPayload":{"position":{"x":28006.356993272086,"y":29714.341642021293},"targetPosition":{"x":28156.356993272086,"y":29454.53402088596},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"e4e268f3-a677-4f90-90a1-d87244e647e5","savedPayload":{"position":{"x":28156.356993272086,"y":29454.53402088596},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"learningMinesData":{"type":"Learning Mines Data","name":"New Learning Mines Data","project":"Superalgos","projectLearningProducts":[{"type":"Project Learning Products","name":"Superalgos","project":"Superalgos","exchangeLearningProducts":[],"id":"071c1c13-0e4c-4649-b2eb-7dc422278961","savedPayload":{"position":{"x":27830.344989097342,"y":29559.98325715586},"targetPosition":{"x":28068.350991184714,"y":29377.354828453244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"2845a687-becc-4c3b-bc79-b2293ba876ba","savedPayload":{"position":{"x":28068.350991184714,"y":29377.354828453244},"targetPosition":{"x":28306.356993272086,"y":29194.726399750627},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e2697759-6038-4943-b90c-5a68651ff9a8","savedPayload":{"position":{"x":28306.356993272086,"y":29194.726399750627},"targetPosition":{"x":28456.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"d"}}},"id":"e452cf65-2b2b-44f2-9e67-bdd9d3c008e4","savedPayload":{"position":{"x":28456.356993272086,"y":28934.918778615294},"targetPosition":{"x":28156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""}}}],"id":"3c165071-7558-4708-9999-8ffe71d346b1","savedPayload":{"position":{"x":28156.356993272086,"y":28934.918778615294},"targetPosition":{"x":28156.356993272086,"y":28934.918778615294},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"s"}}},{"type":"Crypto Ecosystem","name":"My Crypto Ecosystem","project":"Superalgos","cryptoExchanges":[{"type":"Crypto Exchanges","name":"Tested","project":"Superalgos","exchanges":[{"type":"Crypto Exchange","name":"Binanceus","config":"{\n \"codeName\": \"binanceus\",\n \"API\": [\n {\n \"method\": \"fetchTrades\",\n \"fetchType\": \"by Id\",\n \"fetchTradesMethod\": \"publicGetHistoricalTrades\",\n \"firstId\": \"f\"\n }\n ]\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"EUR\"} \n}","project":"Superalgos","assets":[{"type":"Asset","name":"Bitcoin","config":"{ \n\"codeName\": \"BTC\"\n}","project":"Superalgos","id":"5f5e4a94-5090-47d4-8883-cc2325d20bfa","savedPayload":{"position":{"x":19807.079365950267,"y":19153.325102172115},"targetPosition":{"x":19729.43365241951,"y":19443.102850058836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Asset","name":"Tether","config":"{ \n\"codeName\": \"USDT\"\n}","project":"Superalgos","id":"f110bfa0-bd5b-469b-a940-4524c8688136","savedPayload":{"position":{"x":20019.21140030623,"y":19365.45713652808},"targetPosition":{"x":19729.43365241951,"y":19443.102850058836},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"id":"95d2c30f-215b-486e-8119-f4eac0279575","savedPayload":{"position":{"x":19729.43365241951,"y":19443.102850058836},"targetPosition":{"x":19517.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"E"}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","code":"{ \n\"codeName\": \"Write here the code name of the Market here.\"\n}","project":"Superalgos","markets":[{"type":"Market","name":"BTC/USDT","config":"{ \n\"codeName\": \"BTC/USDT\"\n}","project":"Superalgos","baseAsset":{"type":"Market Base Asset","name":"Bitcoin","project":"Superalgos","id":"1017b30d-de1b-4212-991e-9fd0a5b6c814","savedPayload":{"position":{"x":20407.079365950267,"y":19577.589170884043},"targetPosition":{"x":20117.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Asset","name":"Bitcoin","id":"5f5e4a94-5090-47d4-8883-cc2325d20bfa"}}},"quotedAsset":{"type":"Market Quoted Asset","name":"Tether","project":"Superalgos","id":"705c4a67-787a-48cd-a3dc-3a557438bf0b","savedPayload":{"position":{"x":20407.079365950267,"y":19732.880597945557},"targetPosition":{"x":20117.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Asset","name":"Tether","id":"f110bfa0-bd5b-469b-a940-4524c8688136"}}},"id":"9a867bf0-a71d-445c-b99a-75b60bbdce09","savedPayload":{"position":{"x":20117.301618063546,"y":19655.2348844148},"targetPosition":{"x":19817.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2fd80894-900e-44ac-a1a7-56c14124f7a1","savedPayload":{"position":{"x":19817.301618063546,"y":19655.2348844148},"targetPosition":{"x":19517.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b","savedPayload":{"position":{"x":19517.301618063546,"y":19655.2348844148},"targetPosition":{"x":19217.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""},"tutorial":{"status":"Done"}}}],"id":"e3879d63-6f8f-41a3-8ac3-0349c4361722","savedPayload":{"position":{"x":19217.301618063546,"y":19655.2348844148},"targetPosition":{"x":18917.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchanges","name":"Untested","project":"Superalgos","exchanges":[{"type":"Crypto Exchange","name":"ACX","config":"{ \n\"codeName\": \"acx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"ebcb522b-ae58-46d2-9d82-a9b0beec3976","savedPayload":{"position":{"x":17935.64382962515,"y":31014.23747069523},"targetPosition":{"x":17912.64382962515,"y":30954.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b2649588-27c6-442c-b179-f6d8817188b3","savedPayload":{"position":{"x":17954.64382962515,"y":31004.23747069523},"targetPosition":{"x":17912.64382962515,"y":30954.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e9c21b2d-de21-43b5-8b48-51367a8c981c","savedPayload":{"position":{"x":19313.14497226101,"y":30565.583066825377},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"AOFEX","config":"{ \n\"codeName\": \"aofex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"623ef91b-04c0-4bd5-ac0d-b32c809be3ea","savedPayload":{"position":{"x":17973.64382962515,"y":30923.23747069523},"targetPosition":{"x":17950.64382962515,"y":30994.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"9d0b5855-59a6-4dda-9a4b-33d7a44d582e","savedPayload":{"position":{"x":17901.64382962515,"y":30994.23747069523},"targetPosition":{"x":17950.64382962515,"y":30994.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c2e9bb45-97c7-47e8-b13c-56946e673c53","savedPayload":{"position":{"x":19413.67778623216,"y":30647.89853748846},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bequant","config":"{ \n\"codeName\": \"bequant\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"b23c8adf-c880-48fd-b4af-4b4be86cf0e5","savedPayload":{"position":{"x":18059.64382962515,"y":31101.23747069523},"targetPosition":{"x":17960.64382962515,"y":31060.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"523bd94f-68f9-457e-91fd-806c1b95e98d","savedPayload":{"position":{"x":18006.64382962515,"y":31117.23747069523},"targetPosition":{"x":17960.64382962515,"y":31060.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8e928d3e-a2c2-4341-aa2f-b753551c9479","savedPayload":{"position":{"x":19504.72140465123,"y":30740.600980501622},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bibox","config":"{ \n\"codeName\": \"bibox\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"13c1f22c-9a35-4d3f-b000-c96984fd6a2b","savedPayload":{"position":{"x":17995.64382962515,"y":31047.23747069523},"targetPosition":{"x":17929.64382962515,"y":31003.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3c6df49d-70c3-468a-bdd8-6768ce6d3a9d","savedPayload":{"position":{"x":17916.64382962515,"y":31018.23747069523},"targetPosition":{"x":17929.64382962515,"y":31003.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e5f9ee4d-77a3-48ae-b354-b2f6a97d5e47","savedPayload":{"position":{"x":19585.208424334218,"y":30842.603544479174},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BigONE","config":"{ \n\"codeName\": \"bigone\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"3f289513-c1c8-457c-b65a-8cf62b5f5eb5","savedPayload":{"position":{"x":17778.64382962515,"y":31071.23747069523},"targetPosition":{"x":17839.64382962515,"y":31063.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8b365e73-1cee-496a-921f-121cb628a130","savedPayload":{"position":{"x":17798.64382962515,"y":31121.23747069523},"targetPosition":{"x":17839.64382962515,"y":31063.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fb9ee540-bf12-4dda-bf87-cb6b58fce649","savedPayload":{"position":{"x":19654.195208565325,"y":30952.710342620318},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Binance Jersey","config":"{ \n\"codeName\": \"binanceje\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"0b979ea9-7a2d-4744-9517-2dfa632dfafc","savedPayload":{"position":{"x":17852.64382962515,"y":30989.23747069523},"targetPosition":{"x":17933.64382962515,"y":30992.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b9a4497d-20f1-4c61-9a79-444e0fe0ddf4","savedPayload":{"position":{"x":17924.64382962515,"y":30952.23747069523},"targetPosition":{"x":17933.64382962515,"y":30992.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"2782350a-84a2-40ec-87c6-3c8043376a18","savedPayload":{"position":{"x":19710.872950374665,"y":31069.630473388454},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Binance US","config":"{ \n\"codeName\": \"binanceus\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"817ee1cf-b44c-4458-a9c4-a05a17ea0510","savedPayload":{"position":{"x":17943.64382962515,"y":30999.23747069523},"targetPosition":{"x":17898.64382962515,"y":31020.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c6694e9e-74dc-4c2e-9151-90f1d6631b45","savedPayload":{"position":{"x":17937.64382962515,"y":30989.23747069523},"targetPosition":{"x":17898.64382962515,"y":31020.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0b2b67d2-853b-470e-8b13-925956ad5621","savedPayload":{"position":{"x":19754.577155060477,"y":31191.993155151424},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"bitbank","config":"{ \n\"codeName\": \"bitbank\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"eb6b6842-9bf7-450e-baa3-7a87541a1cf6","savedPayload":{"position":{"x":17955.64382962515,"y":31107.23747069523},"targetPosition":{"x":17941.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"6353ff56-759f-457d-81f3-fdb8ae5b3e83","savedPayload":{"position":{"x":17942.64382962515,"y":31183.23747069523},"targetPosition":{"x":17941.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6c9a96a7-ed12-4b3e-bb51-306a8da131f5","savedPayload":{"position":{"x":19784.79543078195,"y":31318.363797342816},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitBay","config":"{ \n\"codeName\": \"bitbay\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"83b4e523-72a7-41ce-9363-fe0c799dcac1","savedPayload":{"position":{"x":17861.64382962515,"y":30965.23747069523},"targetPosition":{"x":17855.64382962515,"y":30961.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"966698f7-8a28-42d7-bb80-f7cd0601e44f","savedPayload":{"position":{"x":17823.64382962515,"y":31026.23747069523},"targetPosition":{"x":17855.64382962515,"y":30961.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8778eee5-97a2-4f9d-bd25-cd5a64ec6663","savedPayload":{"position":{"x":19801.173495885087,"y":31447.26081972472},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitfinex","config":"{ \n\"codeName\": \"bitfinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"33508b53-2769-4f3d-8c98-9fa37e5cbf5b","savedPayload":{"position":{"x":17888.64382962515,"y":31043.23747069523},"targetPosition":{"x":17965.64382962515,"y":30956.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4d4ad5a1-81a7-4f92-83db-99f57ce261bb","savedPayload":{"position":{"x":17975.64382962515,"y":30868.23747069523},"targetPosition":{"x":17965.64382962515,"y":30956.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6c076027-683d-4778-8a6a-e60984980fdf","savedPayload":{"position":{"x":19803.51933253116,"y":31577.173022561386},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitfinex","config":"{ \n\"codeName\": \"bitfinex2\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"8fc7f955-5c81-446c-bbeb-205988bf1fc0","savedPayload":{"position":{"x":17830.64382962515,"y":31051.23747069523},"targetPosition":{"x":17863.64382962515,"y":31062.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d5ba38e9-3282-4634-b922-16532c71f426","savedPayload":{"position":{"x":17819.64382962515,"y":31118.23747069523},"targetPosition":{"x":17863.64382962515,"y":31062.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"f3114102-a73c-4086-9594-5888ef1ab4ec","savedPayload":{"position":{"x":19791.80543793031,"y":31706.577304054405},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bitforex","config":"{ \n\"codeName\": \"bitforex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"698e5e38-ad73-4cb6-b7f6-2b69913faff9","savedPayload":{"position":{"x":17897.64382962515,"y":30956.23747069523},"targetPosition":{"x":17937.64382962515,"y":30945.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"f0142bd4-1b63-4d12-a4b7-e150d0da197f","savedPayload":{"position":{"x":18020.64382962515,"y":31021.23747069523},"targetPosition":{"x":17937.64382962515,"y":30945.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"499a5a3b-7871-4c95-9b2e-d58d4d9e2392","savedPayload":{"position":{"x":19766.169146786622,"y":31833.956517318737},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"bitkk","config":"{ \n\"codeName\": \"bitkk\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"efbb916c-780b-447f-a4c2-df68570d4ee1","savedPayload":{"position":{"x":17931.64382962515,"y":30937.23747069523},"targetPosition":{"x":17951.64382962515,"y":30936.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0d829516-81d9-46a5-9861-7d94cc89455d","savedPayload":{"position":{"x":17951.64382962515,"y":30912.23747069523},"targetPosition":{"x":17951.64382962515,"y":30936.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ded39740-3c93-4fda-bb9c-6ac75d2109f4","savedPayload":{"position":{"x":19726.911021174266,"y":31957.817257542785},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMart","config":"{ \n\"codeName\": \"bitmart\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"10374855-6b4a-460b-9c95-70072ac00315","savedPayload":{"position":{"x":17907.64382962515,"y":30901.23747069523},"targetPosition":{"x":17834.64382962515,"y":30915.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3aded60c-4061-48ff-ad33-212c965b5c43","savedPayload":{"position":{"x":17829.64382962515,"y":30925.23747069523},"targetPosition":{"x":17834.64382962515,"y":30915.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c7ed52a7-895b-46f1-a745-35954d8bcfc6","savedPayload":{"position":{"x":19674.491326722004,"y":32076.707370794375},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMax","config":"{ \n\"codeName\": \"bitmax\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"8a042d0d-7a7a-4a76-889e-42d8642404f4","savedPayload":{"position":{"x":17944.64382962515,"y":31046.23747069523},"targetPosition":{"x":17944.64382962515,"y":31109.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0c4fcc48-51e6-4ff2-925f-405cda6d1122","savedPayload":{"position":{"x":17898.64382962515,"y":31024.23747069523},"targetPosition":{"x":17944.64382962515,"y":31109.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fc6a9048-ab8c-48f9-91ae-6c95c28714b0","savedPayload":{"position":{"x":19609.524636419505,"y":32189.2329791979},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BitMEX","config":"{ \n\"codeName\": \"bitmex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f7636e2b-354a-4217-894b-5e26eddc0c2a","savedPayload":{"position":{"x":17894.64382962515,"y":30934.23747069523},"targetPosition":{"x":17910.64382962515,"y":30922.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"6eb2ddd1-6d06-456c-b4e0-7df56ba182e6","savedPayload":{"position":{"x":17823.64382962515,"y":30834.23747069523},"targetPosition":{"x":17910.64382962515,"y":30922.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"1e2f1dd0-ebf1-4485-83d8-7723a9e3e714","savedPayload":{"position":{"x":19532.77262531095,"y":32294.07482287797},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bittrex","config":"{ \n\"codeName\": \"bittrex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"88d4ef94-f030-42df-9115-69d9611317b1","savedPayload":{"position":{"x":17839.64382962515,"y":31009.23747069523},"targetPosition":{"x":17893.64382962515,"y":30968.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"7fe8234d-9a39-4b28-bf98-43b4fdb57ee5","savedPayload":{"position":{"x":17878.64382962515,"y":31045.23747069523},"targetPosition":{"x":17893.64382962515,"y":30968.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"f598f002-8fc5-491f-888e-07d017ea83c6","savedPayload":{"position":{"x":19445.135140551556,"y":32390.003727075255},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bit-Z","config":"{ \n\"codeName\": \"bitz\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"0a22e02b-7d2e-4955-9cfc-ed7d95f0c9a0","savedPayload":{"position":{"x":17751.64382962515,"y":31083.23747069523},"targetPosition":{"x":17850.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"298b45af-b73d-4cd5-848a-97de7b857569","savedPayload":{"position":{"x":17944.64382962515,"y":31083.23747069523},"targetPosition":{"x":17850.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6cc10926-fe41-43be-887b-fa8aba1c7377","savedPayload":{"position":{"x":19347.639651522415,"y":32475.89501309667},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BTC-Alpha","config":"{ \n\"codeName\": \"btcalpha\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"263e3b9c-8fdd-4376-b53b-87f32d0f5898","savedPayload":{"position":{"x":17904.64382962515,"y":30922.23747069523},"targetPosition":{"x":17883.64382962515,"y":30971.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"804603e1-3e0f-4219-a9b7-ee27810d4f07","savedPayload":{"position":{"x":17829.64382962515,"y":30977.23747069523},"targetPosition":{"x":17883.64382962515,"y":30971.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"30e5485f-213b-435b-a670-07b76cfe5cae","savedPayload":{"position":{"x":19241.429203691412,"y":32550.741684144767},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BTC Markets","config":"{ \n\"codeName\": \"btcmarkets\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"fcb3b880-0852-4d93-8714-67373f9dca16","savedPayload":{"position":{"x":17911.64382962515,"y":31036.23747069523},"targetPosition":{"x":17994.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"953d8eff-0b2e-4b07-8635-393fddae0c9d","savedPayload":{"position":{"x":18025.64382962515,"y":31127.23747069523},"targetPosition":{"x":17994.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ac2fda42-95ca-404a-8dd2-72bff0ff5a0f","savedPayload":{"position":{"x":19127.749017450227,"y":32613.66623143447},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Buda","config":"{ \n\"codeName\": \"buda\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"27f3573d-e1f0-473f-9bfd-f9198e7240a0","savedPayload":{"position":{"x":17945.64382962515,"y":30937.23747069523},"targetPosition":{"x":17853.64382962515,"y":31005.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4ddc0981-4e45-42f3-ae11-f5b136b2bc3d","savedPayload":{"position":{"x":17783.64382962515,"y":31008.23747069523},"targetPosition":{"x":17853.64382962515,"y":31005.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"90fe3d74-662e-4fac-aff3-f41990b61ccf","savedPayload":{"position":{"x":19007.931889043757,"y":32663.930922181273},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"BW","config":"{ \n\"codeName\": \"bw\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"457616cd-25f9-4ad3-8c18-6331859dd42e","savedPayload":{"position":{"x":17890.64382962515,"y":31014.23747069523},"targetPosition":{"x":17900.64382962515,"y":30965.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8c1f9aa2-4253-4129-a533-e515644ddb38","savedPayload":{"position":{"x":17909.64382962515,"y":30970.23747069523},"targetPosition":{"x":17900.64382962515,"y":30965.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d72db90c-d572-4cbb-8348-e3cc485d8e86","savedPayload":{"position":{"x":18883.38256475272,"y":32700.94644884361},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Bybit","config":"{ \n\"codeName\": \"bybit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"18fdf7c8-03c4-4f81-a88e-de97589765e1","savedPayload":{"position":{"x":17803.64382962515,"y":31059.23747069523},"targetPosition":{"x":17855.64382962515,"y":31007.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"a62b2603-ac6f-4b6e-9541-86daf32027b1","savedPayload":{"position":{"x":17847.64382962515,"y":31104.23747069523},"targetPosition":{"x":17855.64382962515,"y":31007.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"516c3831-456b-4d17-b0a0-6a363ba2ddb2","savedPayload":{"position":{"x":18755.561271527895,"y":32724.27883821499},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"ByteTrade","config":"{ \n\"codeName\": \"bytetrade\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e7a1e531-5a9e-466e-b98d-672de39eed3a","savedPayload":{"position":{"x":18088.64382962515,"y":31024.23747069523},"targetPosition":{"x":17991.64382962515,"y":30981.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"edafaba7-fd82-4d9f-b3f7-5d1c01c56599","savedPayload":{"position":{"x":17941.64382962515,"y":30943.23747069523},"targetPosition":{"x":17991.64382962515,"y":30981.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"45e2306f-03e8-4d17-a73a-72c11dd14e78","savedPayload":{"position":{"x":18625.966597164217,"y":32733.65453936303},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CEX.IO","config":"{ \n\"codeName\": \"cex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9de19f0a-5824-4e42-af00-484b64421dc3","savedPayload":{"position":{"x":17890.64382962515,"y":31049.23747069523},"targetPosition":{"x":17896.64382962515,"y":31076.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"39db01bc-0cea-422f-b9e9-7d84e3f5446d","savedPayload":{"position":{"x":17918.64382962515,"y":31105.23747069523},"targetPosition":{"x":17896.64382962515,"y":31076.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"346bfc30-e32a-453a-bdc6-0ead48221581","savedPayload":{"position":{"x":18496.117920729066,"y":32728.96363076407},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Coinbase Prime","config":"{ \n\"codeName\": \"coinbaseprime\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"73cabd8d-9308-49ed-b544-44f785ee7d38","savedPayload":{"position":{"x":17867.64382962515,"y":30962.23747069523},"targetPosition":{"x":17922.64382962515,"y":30960.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"31bd1360-f0c5-4d70-876a-b152f7cedfd7","savedPayload":{"position":{"x":17960.64382962515,"y":30864.23747069523},"targetPosition":{"x":17922.64382962515,"y":30960.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5a8281db-6ace-4186-8cfb-cd249c4af48b","savedPayload":{"position":{"x":18367.537599231866,"y":32710.26110903248},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Coinbase Pro","config":"{ \n\"codeName\": \"coinbasepro\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"a29d6e1a-a94e-4b6b-8741-e9af6e4762f4","savedPayload":{"position":{"x":17788.64382962515,"y":30897.23747069523},"targetPosition":{"x":17841.64382962515,"y":30932.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"10cd9004-0088-4bc0-8fe6-b937f1bb311b","savedPayload":{"position":{"x":17865.64382962515,"y":30918.23747069523},"targetPosition":{"x":17841.64382962515,"y":30932.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4242da4b-a67e-44d8-8a19-b1c2f078c94c","savedPayload":{"position":{"x":18241.733119380056,"y":32677.766244135688},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CoinEx","config":"{ \n\"codeName\": \"coinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"af78f796-60e5-4794-87b8-772c7bc74be1","savedPayload":{"position":{"x":18043.64382962515,"y":31069.23747069523},"targetPosition":{"x":18000.64382962515,"y":31106.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d351e6d9-36eb-4d0e-aca5-94429bbb23a3","savedPayload":{"position":{"x":18094.64382962515,"y":31090.23747069523},"targetPosition":{"x":18000.64382962515,"y":31106.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"62ad0961-6bdf-4a4a-a340-610816742d0a","savedPayload":{"position":{"x":18120.179423675774,"y":32631.860008654276},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"COSS","config":"{ \n\"codeName\": \"coss\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e6315232-c6b1-4e25-aade-7bc7ba9ba6ac","savedPayload":{"position":{"x":17787.64382962515,"y":30984.23747069523},"targetPosition":{"x":17874.64382962515,"y":31049.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b1e8451f-09a2-47b0-add3-cf9c35c487bb","savedPayload":{"position":{"x":17829.64382962515,"y":31095.23747069523},"targetPosition":{"x":17874.64382962515,"y":31049.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"695029de-7f61-45bb-aa4c-c6d51e6369ed","savedPayload":{"position":{"x":18004.301618063546,"y":32573.08061122679},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"CREX24","config":"{ \n\"codeName\": \"crex24\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c5e12f4a-fb26-40d3-9e70-751b55018e74","savedPayload":{"position":{"x":17910.64382962515,"y":31024.23747069523},"targetPosition":{"x":17860.64382962515,"y":31075.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"00cb629e-bad4-4c6e-8abb-499cad3992f4","savedPayload":{"position":{"x":17938.64382962515,"y":31054.23747069523},"targetPosition":{"x":17860.64382962515,"y":31075.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"07a7ec7c-273e-4675-8d8d-21ab8514a1f0","savedPayload":{"position":{"x":17895.458263866083,"y":32502.117186545547},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Deribit","config":"{ \n\"codeName\": \"deribit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f0b2354b-89e3-4eca-b051-664a3b8283f6","savedPayload":{"position":{"x":17862.64382962515,"y":30844.23747069523},"targetPosition":{"x":17906.64382962515,"y":30929.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"4ae1f824-82a8-4796-a2d5-3d2358d8089f","savedPayload":{"position":{"x":17912.64382962515,"y":31024.23747069523},"targetPosition":{"x":17906.64382962515,"y":30929.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"21971815-4248-45df-8e04-20b9a5a83f06","savedPayload":{"position":{"x":17794.92544989493,"y":32419.801715882462},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"DigiFinex","config":"{ \n\"codeName\": \"digifinex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"e583c93e-9a44-4e0d-acb7-56d7e00a555a","savedPayload":{"position":{"x":17954.64382962515,"y":30992.23747069523},"targetPosition":{"x":17996.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8917c7c0-b420-4d4f-a35a-c0fc6870f0de","savedPayload":{"position":{"x":18052.64382962515,"y":30972.23747069523},"targetPosition":{"x":17996.64382962515,"y":31033.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b7d56781-0c51-4ec1-95fd-bf4dc8c00352","savedPayload":{"position":{"x":17703.88183147586,"y":32327.0992728693},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"DSX","config":"{ \n\"codeName\": \"dsx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"d672ab56-cd32-4ff5-8fc5-3733262aeccb","savedPayload":{"position":{"x":17916.64382962515,"y":31106.23747069523},"targetPosition":{"x":17955.64382962515,"y":31011.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"3731a7b5-ba9d-483e-bb41-abf3ae0232c6","savedPayload":{"position":{"x":17878.64382962515,"y":30946.23747069523},"targetPosition":{"x":17955.64382962515,"y":31011.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4c543abc-7372-4701-bc58-107578d45c25","savedPayload":{"position":{"x":17623.394811792878,"y":32225.09670889175},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FCoin","config":"{ \n\"codeName\": \"fcoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"a97d578c-6d7f-403c-8294-18aacf14abd8","savedPayload":{"position":{"x":17893.64382962515,"y":30953.23747069523},"targetPosition":{"x":17919.64382962515,"y":30948.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"442c3834-482e-4928-9255-8ac859ae012e","savedPayload":{"position":{"x":17905.64382962515,"y":30896.23747069523},"targetPosition":{"x":17919.64382962515,"y":30948.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6ddedcbd-07cb-4928-91b3-348f47118391","savedPayload":{"position":{"x":17554.408027561767,"y":32114.989910750606},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FCoinJP","config":"{ \n\"codeName\": \"fcoinjp\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"4a8a9810-6df6-451a-ab26-22bd7e7be85a","savedPayload":{"position":{"x":17930.64382962515,"y":31129.23747069523},"targetPosition":{"x":17942.64382962515,"y":31052.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"138ab40c-18ca-4a11-9709-0baa040873e6","savedPayload":{"position":{"x":18007.64382962515,"y":31122.23747069523},"targetPosition":{"x":17942.64382962515,"y":31052.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"982627ea-df84-4ba9-9219-612fbe1e4276","savedPayload":{"position":{"x":17497.730285752426,"y":31998.069779982467},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"FTX","config":"{ \n\"codeName\": \"ftx\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"20c0a4f5-bdb9-46cc-af7e-2111964551e3","savedPayload":{"position":{"x":17886.64382962515,"y":30940.23747069523},"targetPosition":{"x":17960.64382962515,"y":31019.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"75c99a0b-d3c9-4073-9283-d33e539c36bb","savedPayload":{"position":{"x":17992.64382962515,"y":31061.23747069523},"targetPosition":{"x":17960.64382962515,"y":31019.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0c0bcf5c-2774-423e-9fcf-c512b38dd06d","savedPayload":{"position":{"x":17454.026081066615,"y":31875.707098219504},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Gate.io","config":"{ \n\"codeName\": \"gateio\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"71a15089-9d40-4726-9a41-37d406064164","savedPayload":{"position":{"x":17930.64382962515,"y":30993.23747069523},"targetPosition":{"x":17880.64382962515,"y":31031.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c025e976-c2c6-49de-81ec-48e2f737b412","savedPayload":{"position":{"x":17925.64382962515,"y":31053.23747069523},"targetPosition":{"x":17880.64382962515,"y":31031.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c4028289-4cdb-4da0-90e6-5f93328b8e03","savedPayload":{"position":{"x":17423.807805345143,"y":31749.336456028108},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Gemini","config":"{ \n\"codeName\": \"gemini\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9eb15872-8d15-4086-9920-46909eb5f9e7","savedPayload":{"position":{"x":17951.64382962515,"y":30901.23747069523},"targetPosition":{"x":17971.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"a84dcf06-57c6-47d7-97a0-9f03f3af8b34","savedPayload":{"position":{"x":18045.64382962515,"y":30891.23747069523},"targetPosition":{"x":17971.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"58bf8247-baef-4ea6-a483-7ed8f0ba5043","savedPayload":{"position":{"x":17407.429740242005,"y":31620.439433646203},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"HitBTC","config":"{ \n\"codeName\": \"hitbtc\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"1632c520-fa79-442f-b33b-430cb1356de6","savedPayload":{"position":{"x":17809.64382962515,"y":31086.23747069523},"targetPosition":{"x":17880.64382962515,"y":31069.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"576d1666-dbd3-4914-9fe2-fa05bdf72eea","savedPayload":{"position":{"x":17840.64382962515,"y":31148.23747069523},"targetPosition":{"x":17880.64382962515,"y":31069.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8384fa0b-854c-4c23-846e-a5da0179a738","savedPayload":{"position":{"x":17405.083903595932,"y":31490.527230809537},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"HitBTC","config":"{ \n\"codeName\": \"hitbtc2\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9a29cb9e-ee8d-4315-8532-eef82224b84a","savedPayload":{"position":{"x":17838.64382962515,"y":30922.23747069523},"targetPosition":{"x":17829.64382962515,"y":30949.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"badd79e7-1e21-4dc3-bfa7-8dfb4a6c6267","savedPayload":{"position":{"x":17920.64382962515,"y":30944.23747069523},"targetPosition":{"x":17829.64382962515,"y":30949.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"09c634c2-5aba-49c5-80bc-4fd4175e7f0c","savedPayload":{"position":{"x":17416.79779819678,"y":31361.12294931652},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Huobi Pro","config":"{ \n\"codeName\": \"huobipro\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"86caa38c-5bdf-40e4-b27b-8d8b64319575","savedPayload":{"position":{"x":18071.64382962515,"y":31171.23747069523},"targetPosition":{"x":17996.64382962515,"y":31077.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"001225af-c715-4566-9502-f8f0ac1c4531","savedPayload":{"position":{"x":18040.64382962515,"y":31019.23747069523},"targetPosition":{"x":17996.64382962515,"y":31077.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"967c3914-a76d-4389-9c7e-9c258ae683bd","savedPayload":{"position":{"x":17442.43408934047,"y":31233.743736052187},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Huobi Russia","config":"{ \n\"codeName\": \"huobiru\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"9b7b32d6-a42e-44bb-8065-5aa32b1e844b","savedPayload":{"position":{"x":17980.64382962515,"y":31034.23747069523},"targetPosition":{"x":17957.64382962515,"y":31088.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8d74201c-33cd-4e12-8920-b08d0ef97572","savedPayload":{"position":{"x":17992.64382962515,"y":31105.23747069523},"targetPosition":{"x":17957.64382962515,"y":31088.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"6f97bb5c-8d85-43ee-86a1-33e22cdfbb5e","savedPayload":{"position":{"x":17481.692214952825,"y":31109.882995828142},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"KKEX","config":"{ \n\"codeName\": \"kkex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"daa4e07a-1cd8-4d92-8004-2eabfaa62f77","savedPayload":{"position":{"x":17924.64382962515,"y":31038.23747069523},"targetPosition":{"x":17987.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"cb64951f-d984-4f51-a751-166a316084f3","savedPayload":{"position":{"x":17945.64382962515,"y":31156.23747069523},"targetPosition":{"x":17987.64382962515,"y":31073.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"16ae95ce-796f-4f2b-942c-f98dcbf9cf4b","savedPayload":{"position":{"x":17534.11190940509,"y":30990.99288257655},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Kraken","config":"{ \n\"codeName\": \"kraken\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"747af60f-c8b9-4377-aa6c-172d4137ea23","savedPayload":{"position":{"x":17854.64382962515,"y":31008.23747069523},"targetPosition":{"x":17946.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c75f7d97-9dc2-4d3e-89eb-f8a3d5f16368","savedPayload":{"position":{"x":17916.64382962515,"y":30872.23747069523},"targetPosition":{"x":17946.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"644efe9c-597a-4ddf-9e28-b33fb3b62d3e","savedPayload":{"position":{"x":17599.078599707587,"y":30878.467274173025},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"KuCoin","config":"{ \n\"codeName\": \"kucoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"01ca3037-4ed3-499e-ad6b-e14ca1d4a51f","savedPayload":{"position":{"x":17919.64382962515,"y":30949.23747069523},"targetPosition":{"x":17920.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"8b3c4ce0-98b1-4d46-bd02-6cf44c3dd686","savedPayload":{"position":{"x":17998.64382962515,"y":30978.23747069523},"targetPosition":{"x":17920.64382962515,"y":30924.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d79bc720-68e1-4771-a66a-bcffa30639d3","savedPayload":{"position":{"x":17675.830610816145,"y":30773.625430492953},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"LBank","config":"{ \n\"codeName\": \"lbank\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"def3f9d0-f09e-4e09-8b6d-a4c322a4384b","savedPayload":{"position":{"x":17877.64382962515,"y":31024.23747069523},"targetPosition":{"x":17838.64382962515,"y":31032.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"53eac3c1-96d6-4cb1-b54d-f3f174eaf733","savedPayload":{"position":{"x":17764.64382962515,"y":31036.23747069523},"targetPosition":{"x":17838.64382962515,"y":31032.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"cb2558d6-dab0-4f35-b83f-7cfc161b3d4f","savedPayload":{"position":{"x":17763.468095575536,"y":30677.69652629567},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Mercado Bitcoin","config":"{ \n\"codeName\": \"mercado\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"83ab2c39-e844-496f-bebb-7b8607428902","savedPayload":{"position":{"x":17849.64382962515,"y":31081.23747069523},"targetPosition":{"x":17849.64382962515,"y":30986.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"d69e722e-c71a-462a-8bbd-d3482d0eab21","savedPayload":{"position":{"x":17771.64382962515,"y":30887.23747069523},"targetPosition":{"x":17849.64382962515,"y":30986.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5002072e-145c-4aeb-a611-3e0e4c60ee5d","savedPayload":{"position":{"x":17860.963584604677,"y":30591.805240274254},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"OKCoin","config":"{ \n\"codeName\": \"okcoin\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"1e4dd5c8-0545-4698-8695-c985880243a3","savedPayload":{"position":{"x":17921.64382962515,"y":31043.23747069523},"targetPosition":{"x":17967.64382962515,"y":30969.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"0e188cae-9764-4963-a78b-e5d7ef272522","savedPayload":{"position":{"x":18005.64382962515,"y":30891.23747069523},"targetPosition":{"x":17967.64382962515,"y":30969.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"1f860b4b-2893-4a51-8649-19c47d494a37","savedPayload":{"position":{"x":17967.17403243568,"y":30516.958569226157},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"OKEX","config":"{ \n\"codeName\": \"okex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"7f618566-3d10-4c3c-90b2-7541a5146eeb","savedPayload":{"position":{"x":17770.64382962515,"y":31094.23747069523},"targetPosition":{"x":17847.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"21205576-5d12-452c-814f-eb56182162ae","savedPayload":{"position":{"x":17794.64382962515,"y":31173.23747069523},"targetPosition":{"x":17847.64382962515,"y":31102.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"aa0edec0-8b27-4f94-abce-1e437ce5aba6","savedPayload":{"position":{"x":18080.854218676865,"y":30454.034021936455},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"RightBTC","config":"{ \n\"codeName\": \"rightbtc\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"ade372e9-5070-4fa9-843e-57732c4106c3","savedPayload":{"position":{"x":17999.64382962515,"y":30964.23747069523},"targetPosition":{"x":17991.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"b63d440e-4501-475c-b8a6-2b9a144e32a1","savedPayload":{"position":{"x":17984.64382962515,"y":30901.23747069523},"targetPosition":{"x":17991.64382962515,"y":30935.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c20cd9e1-52a0-4d17-b90c-e9d5b63315ce","savedPayload":{"position":{"x":18200.67134708334,"y":30403.76933118965},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"STEX","config":"{ \n\"codeName\": \"stex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f1d65161-4922-4a1e-ac98-df1a842347a7","savedPayload":{"position":{"x":17872.64382962515,"y":31001.23747069523},"targetPosition":{"x":17892.64382962515,"y":31092.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"c313b2c6-6154-4a9a-b826-fd99cc500cd9","savedPayload":{"position":{"x":17888.64382962515,"y":31186.23747069523},"targetPosition":{"x":17892.64382962515,"y":31092.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0ea23137-3c65-4de1-9772-6ac1b65196e8","savedPayload":{"position":{"x":18325.220671374373,"y":30366.753804527314},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TideBit","config":"{ \n\"codeName\": \"tidebit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c92318bd-8b2d-489b-b8e8-cf30fb63286e","savedPayload":{"position":{"x":17981.64382962515,"y":31021.23747069523},"targetPosition":{"x":17978.64382962515,"y":31048.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"83bca3ec-fc1c-435c-b5fe-b1cf92463fd1","savedPayload":{"position":{"x":18051.64382962515,"y":31072.23747069523},"targetPosition":{"x":17978.64382962515,"y":31048.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5563c310-701a-4c1e-8155-87c08c927ce3","savedPayload":{"position":{"x":18453.041964599197,"y":30343.421415155935},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TimeX","config":"{ \n\"codeName\": \"timex\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"5c004b5f-eec4-414f-8d01-d9b3fddeee9e","savedPayload":{"position":{"x":17892.64382962515,"y":30973.23747069523},"targetPosition":{"x":17949.64382962515,"y":30914.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"59a33add-d0e9-4ae1-8a01-f1e0ed09cb61","savedPayload":{"position":{"x":17911.64382962515,"y":30878.23747069523},"targetPosition":{"x":17949.64382962515,"y":30914.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"27d69fa7-b561-4986-8c0d-1b374e7e1bf1","savedPayload":{"position":{"x":18582.63663896287,"y":30334.045714007894},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"TOP.Q","config":"{ \n\"codeName\": \"topq\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"eafef6a3-eed2-470e-a15c-aa4c10001cd2","savedPayload":{"position":{"x":17818.64382962515,"y":31115.23747069523},"targetPosition":{"x":17847.64382962515,"y":31105.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"2d5eb813-ceb6-40cd-8682-7205596bb8b5","savedPayload":{"position":{"x":17759.64382962515,"y":31188.23747069523},"targetPosition":{"x":17847.64382962515,"y":31105.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8fdf13d8-e8d2-4ef4-8b34-f492a25d753a","savedPayload":{"position":{"x":18712.485315398026,"y":30338.736622606855},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"Upbit","config":"{ \n\"codeName\": \"upbit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"f456fec2-cee6-4f0c-b865-1188088879c9","savedPayload":{"position":{"x":17919.64382962515,"y":30973.23747069523},"targetPosition":{"x":17991.64382962515,"y":30980.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"947c1ca0-bff9-4372-b153-40054e29b705","savedPayload":{"position":{"x":17921.64382962515,"y":31014.23747069523},"targetPosition":{"x":17991.64382962515,"y":30980.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"74e57ecd-3394-42b4-b2c4-6f216f7e41db","savedPayload":{"position":{"x":18841.065636895226,"y":30357.439144338445},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"WhiteBit","config":"{ \n\"codeName\": \"whitebit\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"c16eae45-a568-4b2e-b064-4431bdf34c24","savedPayload":{"position":{"x":17767.64382962515,"y":30899.23747069523},"targetPosition":{"x":17834.64382962515,"y":30950.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"dfdf793f-4ba6-4215-a325-323c0f223553","savedPayload":{"position":{"x":17920.64382962515,"y":31004.23747069523},"targetPosition":{"x":17834.64382962515,"y":30950.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"467ece1e-d1d0-4a11-ae7a-d0e22cd4eba5","savedPayload":{"position":{"x":18966.87011674703,"y":30389.934009235236},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchange","name":"ZB","config":"{ \n\"codeName\": \"zb\"\n}","project":"Superalgos","exchangeAssets":{"type":"Exchange Assets","name":"New Exchange Assets","config":"{ \n\"addMissingAssetsFilter\": { \"quotedAsset\": \"USDT\"} \n}","project":"Superalgos","assets":[],"id":"db206cbd-a587-4e8e-acbe-6581ad3b5cc4","savedPayload":{"position":{"x":17855.64382962515,"y":31027.23747069523},"targetPosition":{"x":17861.64382962515,"y":30951.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"exchangeMarkets":{"type":"Exchange Markets","name":"New Exchange Markets","project":"Superalgos","markets":[],"id":"1dd658c5-7755-44b7-85f0-9bcd787762a0","savedPayload":{"position":{"x":17789.64382962515,"y":31044.23747069523},"targetPosition":{"x":17861.64382962515,"y":30951.23747069523},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"07df07e8-39a8-4fbc-a0c8-150f20b6ac59","savedPayload":{"position":{"x":19088.423812451314,"y":30435.840244716648},"targetPosition":{"x":18604.301618063546,"y":31533.850126685462},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"51f64e29-e3ab-4683-a5de-f397fbf94260","savedPayload":{"position":{"x":18617.301618063546,"y":20174.850126685462},"targetPosition":{"x":18917.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Crypto Exchanges","name":"Testing Queue","project":"Superalgos","exchanges":[],"id":"895ce4b1-4890-4216-89ba-a012181d2546","savedPayload":{"position":{"x":18767.301618063546,"y":19395.427263279467},"targetPosition":{"x":18917.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"signalsProviders":[],"id":"7217b56c-e854-4c06-8b8a-d5d3c05a153d","savedPayload":{"position":{"x":18917.301618063546,"y":19655.2348844148},"targetPosition":{"x":18917.301618063546,"y":19655.2348844148},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":""}}},{"type":"Charting Space","name":"New Charting Space","project":"Superalgos","viewport":{"type":"Viewport","name":"New Viewport","config":"{\"zoom\":\"0.00\"}","project":"Superalgos","id":"01713f1d-91b8-44f9-9c5d-a0c12fd09037","savedPayload":{"position":{"x":22918.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"frame":{"position":{"x":245.62500000000045,"y":440.12500000000006}}}},"projectDashboards":[{"type":"Project Dashboards","name":"Superalgos","project":"Superalgos","dashboards":[{"type":"Dashboard","name":"Testing Environment My Computer","project":"Superalgos","timeMachines":[{"type":"Time Machine","name":"Example Custom Chart","config":"{}","project":"Superalgos","timeScale":{"type":"Time Scale","name":"New Time Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"fromDate\": \"2020-01-01T00:00:00.000Z\",\n \"toDate\": \"2021-01-23T23:59:59.999Z\"\n}","project":"Superalgos","id":"691e2b6e-6b13-4a94-a8cd-15bbad6e8d2b","savedPayload":{"position":{"x":21942.434665834,"y":29653.977644897117},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"rateScale":{"type":"Rate Scale","name":"New Rate Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"minValue\": 3744.3087,\n \"maxValue\": 42369.5\n}","project":"Superalgos","id":"d1c91955-e558-4ffe-a349-895405dd7475","savedPayload":{"position":{"x":21837.45195066214,"y":29705.749390696466},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrameScale":{"type":"Time Frame Scale","name":"New Time Frame Scale","config":"{\"value\":\"24-hs\"}","project":"Superalgos","id":"69064a57-bfa3-4a7a-a597-55887057befb","savedPayload":{"position":{"x":21720.64837946537,"y":29713.405101221888},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timelineCharts":[{"type":"Timeline Chart","name":"Indicators","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Candles Volumes","project":"Superalgos","layers":[{"type":"Layer","name":"Candles","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"550e7d96-2b55-4cb5-91d5-6fbceb32cbb8","savedPayload":{"position":{"x":21459.806237131383,"y":30535.58688508041},"targetPosition":{"x":21459.806237131383,"y":30235.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Candles","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab"}}}],"layerFolders":[],"id":"a9026e9d-f9c2-4509-9a75-862421b5c70b","savedPayload":{"position":{"x":21459.806237131383,"y":30235.58688508041},"targetPosition":{"x":21459.806237131383,"y":29935.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Layers","name":"Resistances and Supports","project":"Superalgos","layers":[{"type":"Layer","name":"Resistances","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"ea7115b6-1324-43dc-8fa2-90c12c2c2c48","savedPayload":{"position":{"x":21049.99861599605,"y":30345.394506215744},"targetPosition":{"x":21199.99861599605,"y":30085.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Resistances","id":"a1669770-1bbe-40f7-acb3-ded15272935f"}}},{"type":"Layer","name":"Supports","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2d16e7e1-8676-4041-a1b1-0172e023558a","savedPayload":{"position":{"x":20899.99861599605,"y":30085.58688508041},"targetPosition":{"x":21199.99861599605,"y":30085.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Supports","id":"64899503-b618-493a-ba94-bfad2051a611"}}}],"layerFolders":[],"id":"b7fed612-b218-4378-bb3f-6c90fb947449","savedPayload":{"position":{"x":21199.99861599605,"y":30085.58688508041},"targetPosition":{"x":21459.806237131383,"y":29935.58688508041},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"aa6b9a8f-d5f4-4f60-b3fa-bdf957806bfb","savedPayload":{"position":{"x":21459.806237131383,"y":29935.58688508041},"targetPosition":{"x":21609.806237131383,"y":29675.779263945078},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":0,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Data Mine Products","name":"Masters","id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0"}}},"id":"6a4b0ce0-7e88-4fe3-b9b5-2116d81b2da0","savedPayload":{"position":{"x":21609.806237131383,"y":29675.779263945078},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading Engine","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Engine","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Episode","project":"Superalgos","layers":[{"type":"Layer","name":"Trading Episode Counters","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fbbb590b-c94d-4625-94e2-bc4bfa2ab6f9","savedPayload":{"position":{"x":17117.615314676776,"y":27603.533941128822},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Counters","id":"a01b42b0-ea87-47ab-b0e9-52d4b10cb631"}}},{"type":"Layer","name":"Trading Episode Statistics","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ab219d3d-1f44-4448-b5f9-f9f6ace6caea","savedPayload":{"position":{"x":17051.16747388602,"y":27764.15503654623},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Statistics","id":"559a20a7-6697-4245-9d6c-ad7c0e31ff84"}}},{"type":"Layer","name":"Episode Candle","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"7dd6f9d6-3840-4a95-a9c9-9445a1335868","savedPayload":{"position":{"x":16933.846232243683,"y":27892.241373813282},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Candle","id":"24fab05f-ff78-4cca-af61-d4d0bb2f2960"}}},{"type":"Layer","name":"Episode Balances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"371bfe04-1b2d-4d60-ae70-03a2f7522466","savedPayload":{"position":{"x":16779.824555577114,"y":27972.466666709206},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Balances","id":"7c580919-08ce-4aff-9e84-888fdf07caec"}}},{"type":"Layer","name":"Distance To Trading Event","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f1dea1ef-69f3-4b64-8586-ec43aa281cde","savedPayload":{"position":{"x":16607.980005705944,"y":27995.20904027392},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Distance To Trading Event","id":"389797d4-8456-4258-9adf-246a6ba69016"}}},{"type":"Layer","name":"Episode Base Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"eca94344-450b-4dc9-ad80-8e202b6e0517","savedPayload":{"position":{"x":16468.146686869968,"y":28016.33671006015},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Base Asset","id":"323c7b0b-42b1-4ff0-9d4b-36c2fd605caa"}}},{"type":"Layer","name":"Episode Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a4c54659-0b38-4faf-9827-47976eb9cca7","savedPayload":{"position":{"x":16286.534133073324,"y":27862.805158861436},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Quoted Asset","id":"63594fc6-3b89-4507-bca8-2d43ef618cbe"}}},{"type":"Layer","name":"Current Episode","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"e82d97df-5b25-4967-b2b4-da065c5d3ad9","savedPayload":{"position":{"x":16186.118842172375,"y":27726.349378357005},"targetPosition":{"x":16629.455267522357,"y":27495.510435539556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Episode","id":"73bb3f9e-b112-4e5a-bce9-6d4bec41cc6c"}}}],"layerFolders":[],"id":"851d853d-e2d7-4138-b5fd-563f1f844f64","savedPayload":{"position":{"x":16629.455267522357,"y":27495.510435539556},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Strategy","project":"Superalgos","layers":[{"type":"Layer","name":"Current Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"dc84698a-bce4-4979-9aca-80661b054191","savedPayload":{"position":{"x":16413.05839477738,"y":27900.48601747122},"targetPosition":{"x":16372.806838862034,"y":27461.836330732353},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Strategy","id":"515f5fd6-d860-44d4-b5d6-a19acd9c5c86"}}},{"type":"Layer","name":"Last Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"d3456e5b-0438-4273-a3ce-6b1d60573c33","savedPayload":{"position":{"x":15940.04282322282,"y":27710.982017672217},"targetPosition":{"x":16372.806838862034,"y":27461.836330732353},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Strategy","id":"556e97e8-eba3-419d-869d-950cc99371da"}}}],"layerFolders":[],"id":"6ad8b449-785f-40cc-afc0-19c68b508c17","savedPayload":{"position":{"x":16372.806838862034,"y":27461.836330732353},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Current Position","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"4b8d055f-0c36-40a6-af78-5faf9b34b72c","savedPayload":{"position":{"x":16011.911411221576,"y":27821.709717793714},"targetPosition":{"x":16167.428268555628,"y":27304.34657839513},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Position","id":"d33abc39-702b-4d7a-8435-43d90e0f2c3a"}}},{"type":"Layer","name":"Last Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ac24a200-397f-4d7c-9916-581328c74f22","savedPayload":{"position":{"x":15678.683136179856,"y":27381.4342703589},"targetPosition":{"x":16167.428268555628,"y":27304.34657839513},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Position","id":"d681fd5f-64af-4f39-9f6d-a767bef7692f"}}}],"layerFolders":[],"id":"acf27818-08f1-4c0d-9cc9-30c38ba892fb","savedPayload":{"position":{"x":16167.428268555628,"y":27304.34657839513},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Open Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"b9eeeeb3-43db-4d4f-9f28-f42e947494f9","savedPayload":{"position":{"x":15829.8024827204,"y":27504.536838373795},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stage","id":"b0961496-1af9-48cd-bbeb-ac5973192e78"}}},{"type":"Layer","name":"Close Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"eda9462a-9688-42cf-ae97-b3dfd02c718c","savedPayload":{"position":{"x":15609.804663880679,"y":27268.796716857654},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stage","id":"0c9cf78d-ce6e-4318-811d-e748ca72845d"}}},{"type":"Layer","name":"Trigger Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"1481d280-6112-4d0d-8a48-3fe4e65efc9d","savedPayload":{"position":{"x":15542.751172927,"y":26994.51154740736},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stage","id":"e298787f-b7f2-4334-931e-38b9441e43f9"}}},{"type":"Layer","name":"Manage Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"2f579332-aa55-4e51-bbf4-370614838fd3","savedPayload":{"position":{"x":15731.678465146957,"y":26701.21391555524},"targetPosition":{"x":16068.487948353533,"y":27065.178022212927},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stage","id":"4719b69d-b23e-4037-8c0a-b641fd8ab14c"}}}],"layerFolders":[],"id":"5b4e1c43-9fb7-439f-9ca9-e600bd41718d","savedPayload":{"position":{"x":16068.487948353533,"y":27065.178022212927},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"be00b86a-5b53-4dbd-ab79-7d135115a05e","savedPayload":{"position":{"x":15729.681254722265,"y":27141.496363567436},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"90834a1b-cc7e-48a9-be5c-0e30380af4bd"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3870b052-156c-4f10-9658-3fe3df4baf10","savedPayload":{"position":{"x":15655.766921038878,"y":26926.520781829942},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"e2112d60-5fc2-4e67-befe-d4fbd6c1de77"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"5fa754c9-ffc3-499c-b566-0031b276cb73","savedPayload":{"position":{"x":15602.003963464067,"y":26726.16283946371},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"e734b6be-ba40-468c-a94f-1153dc85e00c"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"off\"\n}","project":"Superalgos","id":"15ec260c-02f5-46e0-853b-6e751175dac7","savedPayload":{"position":{"x":15694.595933594896,"y":26519.078790508484},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"9a973229-4d9d-45af-b5aa-64906a915f6e"}}},{"type":"Layer","name":"Last Market Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"be57de60-d843-4bc8-bcb8-d8be27ceffbb","savedPayload":{"position":{"x":15860.599521408476,"y":26370.959361875106},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Market Order","id":"56517fe9-64da-4404-83f3-005106bc1c0a"}}},{"type":"Layer","name":"Last Limit Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"407c7816-701b-43bf-92d8-cc728af78f0e","savedPayload":{"position":{"x":16074.514663407172,"y":26309.4257023683},"targetPosition":{"x":16102.435022890473,"y":26808.60560739891},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Limit Order","id":"d00c76e7-4be0-4518-9892-a0f6df943951"}}}],"layerFolders":[],"id":"ac1ed18a-243b-4211-bb24-83bbfc20cd0a","savedPayload":{"position":{"x":16102.435022890473,"y":26808.60560739891},"targetPosition":{"x":16563.94253388532,"y":27000.12691029475},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"41428787-ca89-4ab9-a5cc-29e66e7c486d","savedPayload":{"position":{"x":16563.94253388532,"y":27000.12691029475},"targetPosition":{"x":16959.887378913278,"y":26696.345955873618},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"153096ea-a48c-4ed5-9f8e-49eafa7a779c","savedPayload":{"position":{"x":16959.887378913278,"y":26696.345955873618},"targetPosition":{"x":17356.087169245202,"y":26392.358194020195},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"918bdf6d-3cfe-4c8b-894d-320cc72aef70","savedPayload":{"position":{"x":17356.087169245202,"y":26392.358194020195},"targetPosition":{"x":17752.58716757543,"y":26088.09403049708},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":150,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"f0cc2b79-bae6-4441-a456-9fda5962a74f","savedPayload":{"position":{"x":21521.80023504401,"y":29598.600071512363},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading System","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading System","project":"Superalgos","layers":[{"type":"Layer","name":"Trading System Errors","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"49761e84-d6c2-4c25-9604-fb2ddf93e510","savedPayload":{"position":{"x":16656.868785422477,"y":26432.858992462687},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Errors","id":"a0c29c57-0a20-4084-9697-142300f62f9c"}}},{"type":"Layer","name":"Trading System Highlights","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"622a88bb-151c-48ef-bb99-e093498bf002","savedPayload":{"position":{"x":16532.079378960796,"y":26407.941535439437},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Highlights","id":"aa0fe882-89a8-4811-8988-c589554afe9d"}}},{"type":"Layer","name":"Trading System Values","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fba6a9fb-5e9a-46dd-aa2b-33950f0ec9f1","savedPayload":{"position":{"x":16422.17772780151,"y":26345.322337891994},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Values","id":"bbc65054-b22b-4cbb-816b-529672e2f498"}}},{"type":"Layer","name":"Trading System Status","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4ec0d56a-b497-4d90-9157-094c08930962","savedPayload":{"position":{"x":16337.350686782229,"y":26251.937657405022},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Status","id":"776a3ece-8255-4e80-b60f-85bb818b561f"}}},{"type":"Layer","name":"Trading System Progress","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5db72b24-ad72-49dd-8a32-1256fb25d04a","savedPayload":{"position":{"x":16285.989038785094,"y":26136.930218774854},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Progress","id":"7593aaf9-0505-4b58-9920-235340ff2d2f"}}},{"type":"Layer","name":"Trading System Running","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"cbdfc3db-d5dd-476c-bf02-cf86d8a01300","savedPayload":{"position":{"x":16272.745363533515,"y":26011.773677977748},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Running","id":"3e2e6105-f41f-42e2-bce5-74ebb3b81cbd"}}},{"type":"Layer","name":"Trading System Announcements","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"105a157c-b33a-40d0-9711-19526b04bfda","savedPayload":{"position":{"x":16299.015550574797,"y":25888.784732962406},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Announcements","id":"faab4399-898b-4393-8c27-fa2f3109c60a"}}},{"type":"Layer","name":"Trading System Warnings","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ab8b1fdc-4319-4b37-ae29-333912412215","savedPayload":{"position":{"x":16361.786293229427,"y":25778.482294029163},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Warnings","id":"9ff0f035-ca7f-4e65-a82c-186fa7f09157"}}},{"type":"Layer","name":"Trading System Infos","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"051bd185-3255-41a5-bf62-ea8b27b32ddf","savedPayload":{"position":{"x":16480.783502595135,"y":25721.83855865352},"targetPosition":{"x":16674.50340983706,"y":26032.473650601696},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Infos","id":"04210a59-070a-45f1-a2a0-cf50bd4879f7"}}}],"layerFolders":[],"id":"838dab4e-c0bf-47f3-ac6a-8f815e5e666b","savedPayload":{"position":{"x":16674.50340983706,"y":26032.473650601696},"targetPosition":{"x":17060.504725681127,"y":25928.810868229375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"74e5c728-fd06-4e79-8ec1-32ab2720adf5","savedPayload":{"position":{"x":17060.504725681127,"y":25928.810868229375},"targetPosition":{"x":17476.621526107163,"y":25817.204586634994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8a7bce21-b09a-41e3-b9af-87f1939e9136","savedPayload":{"position":{"x":17183.249075924137,"y":26042.417976975546},"targetPosition":{"x":17666.14324924388,"y":25913.066804430764},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":300,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"a514d9bb-8862-4c81-b82e-dbde66abeb77","savedPayload":{"position":{"x":21470.02848924466,"y":29493.617356340503},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Objects","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 0,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Objects","project":"Superalgos","layers":[{"type":"Layer","name":"Episodes","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"17c8f568-4716-4a19-a607-689b78a83ef9","savedPayload":{"position":{"x":15863.39648009967,"y":25920.19809968253},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episodes","id":"73dff61a-7b05-4ca6-b963-99d6c578e9ba"}}},{"type":"Layer","name":"Strategies","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"86978570-76c1-4780-a91d-4e72e88ef817","savedPayload":{"position":{"x":15705.823183600161,"y":25714.050844388883},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Strategies","id":"a9c454c8-9075-4dcf-bfe9-ebd0c1658049"}}}],"layerFolders":[{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"653e6b00-bda3-4662-a2bd-934212e884d1","savedPayload":{"position":{"x":15327.86442305616,"y":25820.329298596927},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"cad1eecc-e897-4086-b42c-fcfd843c04cc"}}},{"type":"Layer","name":"Market Sell Orders","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2887f930-5d79-42ff-ab1d-7d5cdc6b47da","savedPayload":{"position":{"x":15180.506269267476,"y":25548.319695716105},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"fdf22e85-7071-4847-bdba-e3fb43a616ed"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"3040a2f6-0b1c-4ed3-a816-39c916465c9a","savedPayload":{"position":{"x":15221.387997903394,"y":25243.251366030032},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"d2b1ab31-d8a1-422b-a717-33ee7df9b07b"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"a59ef70f-534f-410b-99ef-3a700d2ca82a","savedPayload":{"position":{"x":15398.72702979423,"y":25036.45705462772},"targetPosition":{"x":15672.454225865862,"y":25457.66729056814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"3b5a12db-b969-4400-8b9d-afb9b7b81642"}}}],"layerFolders":[],"id":"334a2964-17df-4237-a302-962416655896","savedPayload":{"position":{"x":15672.454225865862,"y":25457.66729056814},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Trigger Stages","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"a6b1a2c5-ca70-42b9-932f-2ff00aff2524","savedPayload":{"position":{"x":15292.017678857432,"y":25360.154463716302},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stages","id":"9fc29be1-9393-4933-95d3-bebddd73c05e"}}},{"type":"Layer","name":"Open Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"663ddaf7-784f-4baa-8f69-3ed0ef5cd685","savedPayload":{"position":{"x":15298.823311983959,"y":25050.998457959326},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stages","id":"b555388f-db93-4db1-91be-7772550afa70"}}},{"type":"Layer","name":"Manage Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"9a4be770-082c-4d0f-a747-0b74d792e76f","savedPayload":{"position":{"x":15476.277795953174,"y":24812.240105588095},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stages","id":"41953904-e48c-4176-bf0f-09d133bc444c"}}},{"type":"Layer","name":"Close Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"efb9d388-a679-49b2-b792-1b8258a489d6","savedPayload":{"position":{"x":15784.125039599678,"y":24724.90131904347},"targetPosition":{"x":15771.52653783795,"y":25218.00065188687},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stages","id":"47b4553c-7f2e-438c-9f4b-9ba30e943a6c"}}}],"layerFolders":[],"id":"eea75e9a-a735-4db8-9eea-cf2c4e4119e3","savedPayload":{"position":{"x":15771.52653783795,"y":25218.00065188687},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Positions","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb0ea641-23a7-48d0-a70d-f3314722f129","savedPayload":{"position":{"x":15517.085211279895,"y":24978.036206455075},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Positions","id":"6e49b57f-8c94-410f-985b-82c126155b11"}}},{"type":"Layer","name":"Position Base Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"fa1cf76f-30a6-4cfd-ba4f-8511afca64b8","savedPayload":{"position":{"x":15592.85911518537,"y":24750.27204370447},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Base Asset","id":"ae8fa9a5-95b6-4769-8ade-f9854e6855ba"}}},{"type":"Layer","name":"Position Quoted Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"bf7d5c92-8894-4040-8d2f-3f5cdec443af","savedPayload":{"position":{"x":15786.287615627753,"y":24593.84817912013},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Quoted Asset","id":"9e9b19ee-9c51-4586-b74d-d2880f13f71f"}}},{"type":"Layer","name":"Stop Loss","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"125c9155-a747-4ac4-9d9f-1b93a4ae8d17","savedPayload":{"position":{"x":16042.541437710524,"y":24564.41238111062},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Stop Loss","id":"01491591-0462-453c-91e0-6da6f554a729"}}},{"type":"Layer","name":"Take Profit","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"3745d5cd-a2be-43ed-b5df-d05c328f8665","savedPayload":{"position":{"x":16280.917386265202,"y":24663.928419862754},"targetPosition":{"x":15977.296572394282,"y":25060.75923245295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Take Profit","id":"719dd8a6-58ab-41c6-9693-9b67c12232d2"}}}],"layerFolders":[],"id":"9854e8b2-d863-42f3-afd5-416d5e2c548e","savedPayload":{"position":{"x":15977.296572394282,"y":25060.75923245295},"targetPosition":{"x":16168.303357177294,"y":25522.64736240649},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"6e31ae33-68d1-4dca-8b29-6e59a2a4448e","savedPayload":{"position":{"x":16168.303357177294,"y":25522.64736240649},"targetPosition":{"x":16663.0166511096,"y":25588.08600416838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8c851b59-3105-460c-bb4b-cb4944db1049","savedPayload":{"position":{"x":16663.0166511096,"y":25588.08600416838},"targetPosition":{"x":17157.9116821377,"y":25653.201834587282},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"be53f7bc-6c26-4fd7-a0d0-96b965bbf655","savedPayload":{"position":{"x":17157.9116821377,"y":25653.201834587282},"targetPosition":{"x":17653.521538239824,"y":25718.280363218284},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":450,"y":80},"width":150,"height":40,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"13a2b4f9-2c05-49b2-b42c-32ffa71ae0b7"}}},"id":"43eeb152-b0b8-468d-84d1-7d03fd636387","savedPayload":{"position":{"x":21462.37277871924,"y":29376.81378514373},"targetPosition":{"x":21759.806237131383,"y":29415.971642809745},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"499eac86-6c40-4362-a36a-5f2002081866","savedPayload":{"position":{"x":22018.806237131383,"y":29379.971642809745},"targetPosition":{"x":22168.806237131383,"y":29120.164021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":585,"y":-155},"width":240,"height":111.125,"radius":0},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}}],"id":"885265c2-ebb1-4283-a617-34a88780276d","savedPayload":{"position":{"x":22168.806237131383,"y":29120.164021674413},"targetPosition":{"x":22318.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Testing Environment","name":"New Testing Environment","id":"5882d8a8-345b-4188-b1c1-797e9ff805d9"}}},{"type":"Dashboard","name":"Production Environment My Computer","project":"Superalgos","timeMachines":[{"type":"Time Machine","name":"Lightning Strike Live Trading Session","config":"{}","project":"Superalgos","timeScale":{"type":"Time Scale","name":"New Time Scale","config":"{\n \"autoMinScale\": false,\n \"autoMaxScale\": false,\n \"fromDate\": \"2020-10-06T17:09:32.085Z\",\n \"toDate\": \"2020-10-06T21:09:32.085Z\"\n}","project":"Superalgos","id":"708c5a9f-a995-4210-aaaf-0794782f0e9e","savedPayload":{"position":{"x":21721.37277871924,"y":28379.89901593443},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"rateScale":{"type":"Rate Scale","name":"New Rate Scale","config":"{\n \"autoMinScale\": true,\n \"autoMaxScale\": true,\n \"minValue\": 10419.75,\n \"maxValue\": 10844.37\n}","project":"Superalgos","id":"ee3f6af0-8649-489b-9168-b4f16d2f5a78","savedPayload":{"position":{"x":21729.02848924466,"y":28263.095444737657},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timeFrameScale":{"type":"Time Frame Scale","name":"New Time Frame Scale","config":"{\n \"value\": \"01-min\",\n \"autoMinScale\": false,\n \"autoMaxScale\": true,\n \"fromDate\": \"2020-10-05T09:53:58.939Z\",\n \"toDate\": \"2020-10-05T13:53:58.939Z\"\n}","project":"Superalgos","id":"480f9696-76df-4026-a435-7bf364c08056","savedPayload":{"position":{"x":21780.80023504401,"y":28158.112729565797},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"timelineCharts":[{"type":"Timeline Chart","name":"New Data Mine Products","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Candles Volumes","project":"Superalgos","layers":[{"type":"Layer","name":"Candles","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"e3cbbcbe-c938-4669-b670-c317476e0a3b","savedPayload":{"position":{"x":16992.282280946285,"y":23856.49271176323},"targetPosition":{"x":17392.615945713467,"y":23857.108132968406},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Candles","id":"b9c30464-73e5-4f5c-b422-9ba1a02b78ab"}}},{"type":"Layer","name":"Volumes","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"385a5f98-118a-43fd-b019-54e825d1f4ae","savedPayload":{"position":{"x":17192.242023030805,"y":23510.135246216414},"targetPosition":{"x":17392.615945713467,"y":23857.108132968406},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Volumes","id":"07c11481-7dbd-477d-8bf7-79212542a6aa"}}}],"layerFolders":[],"id":"6848a114-9979-41dd-8d95-3a899679ba08","savedPayload":{"position":{"x":17392.615945713467,"y":23857.108132968406},"targetPosition":{"x":17738.764681458488,"y":24056.665358937673},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Bot Layers","name":"Resistances and Supports","project":"Superalgos","layers":[{"type":"Layer","name":"Resistances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"0cf13cfa-2a37-4691-902c-513ab5780da8","savedPayload":{"position":{"x":17538.760168957182,"y":23310.0159698544},"targetPosition":{"x":17738.97910230742,"y":23657.072015580987},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Resistances","id":"a1669770-1bbe-40f7-acb3-ded15272935f"}}},{"type":"Layer","name":"Supports","config":"{\n \"status\": \"off\",\n \"showPanels\": false\n}","project":"Superalgos","id":"d9245f0b-54e8-44b1-94bd-56c7048eb5c1","savedPayload":{"position":{"x":17938.505496583897,"y":23310.043709247824},"targetPosition":{"x":17738.97910230742,"y":23657.072015580987},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Supports","id":"64899503-b618-493a-ba94-bfad2051a611"}}}],"layerFolders":[],"id":"20bd60bb-917b-4a0f-acc5-b019d1c3bd81","savedPayload":{"position":{"x":17738.97910230742,"y":23657.072015580987},"targetPosition":{"x":17738.764681458488,"y":24056.665358937673},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"4cbbc012-c91e-4acd-a8d2-feb149e728a0","savedPayload":{"position":{"x":17738.764681458488,"y":24056.665358937673},"targetPosition":{"x":17963.331767523672,"y":24445.732145877373},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":0,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Data Mine Products","name":"Masters","id":"d37d8bf1-be3b-49ac-805b-0ddb3944e6a0"}}},"id":"bb7afb85-32ea-4471-8400-615a34fc126f","savedPayload":{"position":{"x":21868.806237131383,"y":28080.93353713308},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading Engine","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Engine","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading Episode","project":"Superalgos","layers":[{"type":"Layer","name":"Trading Episode Counters","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"05da2270-0016-4d22-89d8-b77cd14008a9","savedPayload":{"position":{"x":12224.806237131383,"y":25700.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Counters","id":"dc6cc4ef-4bd7-4837-8442-919462314db3"}}},{"type":"Layer","name":"Trading Episode Statistics","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a4165460-e0a7-4a0d-b506-15e756dfac93","savedPayload":{"position":{"x":12219.806237131383,"y":25689.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading Episode Statistics","id":"776ed571-8321-47aa-8cfb-c8ebf565dace"}}},{"type":"Layer","name":"Episode Candle","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"371e0cd7-af57-4469-836d-45c4e6059760","savedPayload":{"position":{"x":12317.806237131383,"y":25717.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Candle","id":"ded93703-a48d-44be-9703-878c28f949cd"}}},{"type":"Layer","name":"Episode Balances","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5ed81442-77cc-4101-b1ff-8c7cbac57d4f","savedPayload":{"position":{"x":12245.806237131383,"y":25698.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Balances","id":"e702f1dd-1c91-4d05-ac55-19db363f5f3a"}}},{"type":"Layer","name":"Distance To Trading Event","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5e046a6a-4f38-4b44-bae1-1aed6d4d3753","savedPayload":{"position":{"x":12313.806237131383,"y":25819.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Distance To Trading Event","id":"b8abea53-8221-47bd-91a2-cdcdd2ad1027"}}},{"type":"Layer","name":"Episode Base Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"b78a78ec-dca3-499b-881a-d2e3a82bf116","savedPayload":{"position":{"x":12330.806237131383,"y":25734.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Base Asset","id":"18bcbd26-c237-4acb-96f4-d9c95d833a42"}}},{"type":"Layer","name":"Episode Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb95c2a9-6f82-4a2a-9105-17b8f6c3c51a","savedPayload":{"position":{"x":12364.806237131383,"y":25720.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episode Quoted Asset","id":"c444f4b5-fa67-4c21-afa8-1f998da7a2a2"}}},{"type":"Layer","name":"Current Episode","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4ad5b6f0-f4a9-4aab-aedf-9175647498b0","savedPayload":{"position":{"x":12321.806237131383,"y":25708.664021674413},"targetPosition":{"x":12315.806237131383,"y":25752.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Episode","id":"057570bd-69d4-4f3c-b0d4-94ee32f61e65"}}}],"layerFolders":[],"id":"7216b7a3-1371-4f07-a395-74c547579ab4","savedPayload":{"position":{"x":12315.806237131383,"y":25752.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Strategy","project":"Superalgos","layers":[{"type":"Layer","name":"Current Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"d2c0a1c8-70ef-4f7b-835a-a99ac6a5837a","savedPayload":{"position":{"x":12210.806237131383,"y":25770.664021674413},"targetPosition":{"x":12305.806237131383,"y":25783.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Strategy","id":"88dd680c-a81b-48ae-96ba-838281abfa35"}}},{"type":"Layer","name":"Last Strategy","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"076af680-2114-480b-a979-f7eea4966d7b","savedPayload":{"position":{"x":12302.806237131383,"y":25739.664021674413},"targetPosition":{"x":12305.806237131383,"y":25783.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Strategy","id":"24af3ffc-6a52-4ee3-a30b-f068aa5b2062"}}}],"layerFolders":[],"id":"56112c60-50dd-4d19-89aa-1d46005f194f","savedPayload":{"position":{"x":12305.806237131383,"y":25783.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Current Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bb93ebef-f7ee-42c2-93b8-fe46eba0874a","savedPayload":{"position":{"x":12424.806237131383,"y":25721.664021674413},"targetPosition":{"x":12427.806237131383,"y":25692.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Current Position","id":"25280962-e4e5-40df-9e42-9edfbad6f6d3"}}},{"type":"Layer","name":"Last Position","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"595e7228-5676-4f5c-82bf-baa43e9325ab","savedPayload":{"position":{"x":12488.806237131383,"y":25680.664021674413},"targetPosition":{"x":12427.806237131383,"y":25692.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Position","id":"7a95a249-132d-4e0f-9182-cc7af45cacea"}}}],"layerFolders":[],"id":"9f594c8a-87fe-4c4b-b550-493405fe0b2d","savedPayload":{"position":{"x":12427.806237131383,"y":25692.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Open Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3ce44f39-8ac9-4984-ad9d-daa53ed3f707","savedPayload":{"position":{"x":12377.806237131383,"y":25588.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stage","id":"c9c4bca7-f918-4aa8-b538-ffe8aa31d5c2"}}},{"type":"Layer","name":"Close Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a7d5f0aa-8259-4271-aa95-7b351aa9b9c0","savedPayload":{"position":{"x":12337.806237131383,"y":25588.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stage","id":"4201d7c0-43aa-4ac0-bd7e-ab26b688aa2d"}}},{"type":"Layer","name":"Trigger Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"9a9f6580-ab06-4005-9274-98f7e9a491e5","savedPayload":{"position":{"x":12387.806237131383,"y":25625.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stage","id":"4fe24ddc-973f-4a5d-bf8a-d77090486125"}}},{"type":"Layer","name":"Manage Stage","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f60905ad-b491-45ee-9768-8087df9aef78","savedPayload":{"position":{"x":12466.806237131383,"y":25757.664021674413},"targetPosition":{"x":12422.806237131383,"y":25658.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stage","id":"e2f3d69e-2f0a-4463-8e74-4f0768c4fb70"}}}],"layerFolders":[],"id":"5389c77c-63a7-4495-9cc5-cdc0c70b76e6","savedPayload":{"position":{"x":12422.806237131383,"y":25658.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f602d8ef-b6a6-423f-a772-9a4b5d5b9c43","savedPayload":{"position":{"x":12422.806237131383,"y":25747.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"0e0b284a-5014-4ab0-ada0-4322c14a099e"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"0a0dd259-5704-46de-900f-5d1dc24af4f6","savedPayload":{"position":{"x":12488.806237131383,"y":25650.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"95b3db7a-9b62-4eab-a76b-4af8794da5a6"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"de6f83f6-a6d9-45c7-93fd-e2c72238040e","savedPayload":{"position":{"x":12410.806237131383,"y":25733.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"1c6eed42-23aa-4174-aade-be29222acb8c"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"ac0f1c2a-5eed-45ee-84da-3d24e455abd3","savedPayload":{"position":{"x":12379.806237131383,"y":25663.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"a2f44cd5-090d-42e5-9eb7-73e732310e85"}}},{"type":"Layer","name":"Last Market Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"89def699-c33f-4344-a045-babca1f545ee","savedPayload":{"position":{"x":12478.806237131383,"y":25752.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Market Order","id":"8c24d559-ba52-46fe-81b4-8a6bf50c74b6"}}},{"type":"Layer","name":"Last Limit Order","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a7e04514-bf32-4021-822c-47af56c55a76","savedPayload":{"position":{"x":12504.806237131383,"y":25780.664021674413},"targetPosition":{"x":12437.806237131383,"y":25742.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Last Limit Order","id":"c451c035-5ece-451f-836f-b5334cb3f967"}}}],"layerFolders":[],"id":"a302255a-cf35-4801-ae3c-95cb47ae9613","savedPayload":{"position":{"x":12437.806237131383,"y":25742.664021674413},"targetPosition":{"x":12363.806237131383,"y":25731.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1857004e-2f12-4287-8847-173043d8d2ab","savedPayload":{"position":{"x":12363.806237131383,"y":25731.664021674413},"targetPosition":{"x":12380.806237131383,"y":25686.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"23ad1663-d4da-4ece-8964-30012894ae5b","savedPayload":{"position":{"x":12380.806237131383,"y":25686.664021674413},"targetPosition":{"x":12448.806237131383,"y":25597.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ddb3fafa-58f4-46c1-9b24-61efe3ec13a6","savedPayload":{"position":{"x":21940.490521799355,"y":27745.87424144413},"targetPosition":{"x":21979.64837946537,"y":28043.307699856272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":150,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"788a0207-20ea-411c-862d-b1b13db4e09f","savedPayload":{"position":{"x":21979.64837946537,"y":28043.307699856272},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Trading System","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Trading System","project":"Superalgos","layers":[{"type":"Layer","name":"Trading System Errors","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"2a1db97f-553d-47ea-b452-c90ba9af9e79","savedPayload":{"position":{"x":12242.806237131383,"y":25582.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Errors","id":"ba606f99-2ae5-44dc-b7db-399e657830e1"}}},{"type":"Layer","name":"Trading System Highlights","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"3c1c9d45-c482-4374-92ad-c3c28bfb7679","savedPayload":{"position":{"x":12270.806237131383,"y":25723.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Highlights","id":"2d20d8ae-4afa-4e92-8de2-89e66e5efdee"}}},{"type":"Layer","name":"Trading System Values","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"a560c8af-91cd-4aea-ab9f-01ed60892abb","savedPayload":{"position":{"x":12340.806237131383,"y":25546.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Values","id":"f8a6219c-c7b4-410a-8aa4-1910583f51c8"}}},{"type":"Layer","name":"Trading System Status","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"40debb84-1e2e-452b-99ff-95ff3994fb29","savedPayload":{"position":{"x":12322.806237131383,"y":25605.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Status","id":"dcff6f56-7646-4505-aa93-6682a110f3f2"}}},{"type":"Layer","name":"Trading System Progress","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"5785c4fb-879d-4b89-aab8-9ec37d5f561b","savedPayload":{"position":{"x":12240.806237131383,"y":25559.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Progress","id":"0a9dff80-e462-4110-b988-11ce57bbbcd5"}}},{"type":"Layer","name":"Trading System Running","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"74d8c1f7-8dd5-4e2c-b3cf-7f7bcfe7143c","savedPayload":{"position":{"x":12342.806237131383,"y":25543.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Running","id":"c7e05ad0-7d4a-4ffb-9aee-191511f85ee7"}}},{"type":"Layer","name":"Trading System Announcements","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"4476fcb1-3898-440f-b69e-afba06be912a","savedPayload":{"position":{"x":12402.806237131383,"y":25585.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Announcements","id":"e4811789-fd94-49b0-9917-8d9d434f997d"}}},{"type":"Layer","name":"Trading System Warnings","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"43fe3418-9b3c-4cd9-b9a9-3994851e0b65","savedPayload":{"position":{"x":12310.806237131383,"y":25555.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Warnings","id":"029ff3a7-9c65-425f-855a-882df68fa05b"}}},{"type":"Layer","name":"Trading System Infos","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"de34ba07-61b5-4785-bcf5-ff5b81d63e48","savedPayload":{"position":{"x":12227.806237131383,"y":25559.664021674413},"targetPosition":{"x":12310.806237131383,"y":25627.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trading System Infos","id":"0f47adaf-25a0-431f-b15b-0fbf44069b38"}}}],"layerFolders":[],"id":"36e02794-0943-4520-af39-2f274050610c","savedPayload":{"position":{"x":12310.806237131383,"y":25627.664021674413},"targetPosition":{"x":12365.806237131383,"y":25585.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1ccfa34c-ca21-4ac3-be74-30f85549bf5e","savedPayload":{"position":{"x":12365.806237131383,"y":25585.664021674413},"targetPosition":{"x":12339.806237131383,"y":25637.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c1c4bd7c-b755-461a-a5ed-b59804b4c280","savedPayload":{"position":{"x":12339.806237131383,"y":25637.664021674413},"targetPosition":{"x":12377.806237131383,"y":25540.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":300,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"ed6507e7-437f-4740-a897-11dc4da4d20a","savedPayload":{"position":{"x":22096.45195066214,"y":28050.963410381693},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Timeline Chart","name":"Objects","project":"Superalgos","layerManager":{"type":"Layer Manager","name":"Masters","config":"{\n \"visibleLayers\": 4,\n \"panelLocation\": {\n \"upOrDown\": \"up\",\n \"leftOrRight\": \"left\"\n }\n}","project":"Superalgos","layers":[],"botLayers":[{"type":"Bot Layers","name":"Low Frequency","project":"Superalgos","layers":[],"layerFolders":[{"type":"Layer Folder","name":"Objects","project":"Superalgos","layers":[{"type":"Layer","name":"Episodes","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"76852fcc-d524-43b8-a0b1-8645c2fed91e","savedPayload":{"position":{"x":12710.806237131383,"y":25614.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Episodes","id":"c6fd6067-4b57-4860-ae3b-5668e4444490"}}},{"type":"Layer","name":"Strategies","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"43b43957-23d5-401b-b3e0-391c430b72c9","savedPayload":{"position":{"x":12705.806237131383,"y":25579.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Strategies","id":"60f88096-7343-42d1-afad-83fecd22fb44"}}}],"layerFolders":[{"type":"Layer Folder","name":"Orders","project":"Superalgos","layers":[{"type":"Layer","name":"Market Buy Orders","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"aaff7fb6-bd83-48f2-819a-a1dd674876a7","savedPayload":{"position":{"x":12579.806237131383,"y":25470.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Buy Orders","id":"9f939086-c934-4924-8353-776707a7cf10"}}},{"type":"Layer","name":"Market Sell Orders","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"bec241f4-5a8f-4fe7-9620-76d92f64da9c","savedPayload":{"position":{"x":12705.806237131383,"y":25579.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Market Sell Orders","id":"da5f279e-d387-43cf-80f4-fc114b9ac906"}}},{"type":"Layer","name":"Limit Buy Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"2d03d083-7199-4bf2-8e8a-4c96f23a16a8","savedPayload":{"position":{"x":12735.806237131383,"y":25521.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Buy Orders","id":"367646bb-839a-4071-8305-6d26a647585d"}}},{"type":"Layer","name":"Limit Sell Orders","config":"{\n \"status\": \"on\",\n \"showPanels\": false\n}","project":"Superalgos","id":"cb5de20d-e440-4bdb-a074-c408740e9022","savedPayload":{"position":{"x":12631.806237131383,"y":25476.664021674413},"targetPosition":{"x":12649.806237131383,"y":25488.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Limit Sell Orders","id":"0b2fc73a-9635-40b2-98d8-0c79c69175a9"}}}],"layerFolders":[],"id":"a8409c29-905d-495f-bbca-3d0eef14f91c","savedPayload":{"position":{"x":12649.806237131383,"y":25488.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Stages","project":"Superalgos","layers":[{"type":"Layer","name":"Trigger Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"04d1a0a8-1419-4fbd-9c28-eef6cfefd5d4","savedPayload":{"position":{"x":12584.806237131383,"y":25552.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Trigger Stages","id":"7fe8c58f-9cad-47c9-ba4e-d66bff094dcf"}}},{"type":"Layer","name":"Open Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"74cda6e5-4fe2-41ef-a611-2c0374780ad5","savedPayload":{"position":{"x":12663.806237131383,"y":25503.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Open Stages","id":"41f17745-1819-4681-8a2b-9bdda3cd67c4"}}},{"type":"Layer","name":"Manage Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"fb041378-9424-4709-a9ed-79426fcdfe68","savedPayload":{"position":{"x":12721.806237131383,"y":25661.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Manage Stages","id":"e89c8bfd-fac9-4aff-afc0-3a89c1dc2710"}}},{"type":"Layer","name":"Close Stages","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"6c4ac373-c5ff-4bfd-8047-4caaba6b7788","savedPayload":{"position":{"x":12659.806237131383,"y":25585.664021674413},"targetPosition":{"x":12680.806237131383,"y":25593.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Close Stages","id":"bc2c6503-e935-4ad7-a76a-89b062d41e91"}}}],"layerFolders":[],"id":"4b2ee5fd-d4f7-4a7c-bb6e-5e4c633b1b9f","savedPayload":{"position":{"x":12680.806237131383,"y":25593.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Layer Folder","name":"Position","project":"Superalgos","layers":[{"type":"Layer","name":"Positions","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"4f77d851-9e93-4e85-9cfb-ec2ab200d79b","savedPayload":{"position":{"x":12581.806237131383,"y":25650.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Positions","id":"3ed594a0-8452-4bd8-9eaa-37cd83a45b90"}}},{"type":"Layer","name":"Position Base Asset","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"0213c668-a6d8-4737-ae57-d59d62b8f715","savedPayload":{"position":{"x":12767.806237131383,"y":25594.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Base Asset","id":"88997c97-e77f-490e-9eb5-c7531beec132"}}},{"type":"Layer","name":"Position Quoted Asset","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"f07986eb-010f-46cd-803d-dcac674adb80","savedPayload":{"position":{"x":12745.806237131383,"y":25673.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Position Quoted Asset","id":"b4772611-d5d0-4fbd-b689-d42de3c045d4"}}},{"type":"Layer","name":"Stop Loss","config":"{\n \"status\": \"off\",\n \"showPanels\": true\n}","project":"Superalgos","id":"3f8f8fa3-2149-42d6-92e9-214354cfa186","savedPayload":{"position":{"x":12630.806237131383,"y":25581.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Stop Loss","id":"9b064960-3829-441f-b955-334fb8324a53"}}},{"type":"Layer","name":"Take Profit","config":"{ \n\"status\": \"off\"\n}","project":"Superalgos","id":"65ec58e6-2c00-41d4-a145-e6b7e7178bf0","savedPayload":{"position":{"x":12743.806237131383,"y":25590.664021674413},"targetPosition":{"x":12672.806237131383,"y":25618.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Product","name":"Take Profit","id":"cbcc817b-4333-4c80-addc-e2a0ee0845c1"}}}],"layerFolders":[],"id":"66e5c011-9163-422d-863f-115135f832ad","savedPayload":{"position":{"x":12672.806237131383,"y":25618.664021674413},"targetPosition":{"x":12687.806237131383,"y":25530.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"91b8a8e8-823d-4746-967f-c8d85a1ad3ad","savedPayload":{"position":{"x":12687.806237131383,"y":25530.664021674413},"targetPosition":{"x":12591.806237131383,"y":25565.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"dcaccce7-d98d-49b3-b3b6-e83495b688c3","savedPayload":{"position":{"x":12591.806237131383,"y":25565.664021674413},"targetPosition":{"x":12523.806237131383,"y":25633.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e328f755-80a6-4799-8f12-002a2ddb983d","savedPayload":{"position":{"x":12523.806237131383,"y":25633.664021674413},"targetPosition":{"x":12489.806237131383,"y":25562.664021674413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":450,"y":80},"width":150,"height":330,"radius":0},"referenceParent":{"type":"Trading Mine Products","name":"Masters","id":"aa2b0766-a3d5-47e1-acd8-7345af564388"}}},"id":"93708a53-ad8d-48e0-9728-b87ea96d1545","savedPayload":{"position":{"x":22201.434665834,"y":28102.735156181043},"targetPosition":{"x":22018.806237131383,"y":28340.741158268414},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"cc1fcc1e-81de-4011-8e59-c37ebe32ecf7","savedPayload":{"position":{"x":22018.806237131383,"y":28340.741158268414},"targetPosition":{"x":22168.806237131383,"y":28600.548779403747},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":585,"y":65},"width":240,"height":113.625,"radius":0},"referenceParent":{"type":"Live Trading Session","name":"Lightning Strike","id":"1ce123af-467f-4295-b317-dba8729faf25"}}}],"id":"abc16155-6614-4397-bf7e-ab4a0ff7c1a4","savedPayload":{"position":{"x":22168.806237131383,"y":28600.548779403747},"targetPosition":{"x":22318.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Production Environment","name":"New Production Environment","id":"65a40d20-837c-4652-8356-f8054b4e1346"}}}],"id":"84a1b1ba-4888-4eac-8762-7084f0ee5de7","savedPayload":{"position":{"x":22318.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Project Definition","name":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb"}}}],"id":"21d2ec55-9e56-4652-8e96-c7e451262c36","savedPayload":{"position":{"x":22618.806237131383,"y":28860.35640053908},"targetPosition":{"x":22618.806237131383,"y":28860.35640053908},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false,"shortcutKey":"c"}}},{"type":"Plugins","name":"New Plugins","project":"Superalgos","pluginProjects":[{"type":"Plugin Project","name":"Superalgos","config":"{ \n \"codeName\": \"Superalgos\"\n}","project":"Superalgos","pluginDataMines":{"type":"Plugin Data Mines","name":"New Plugin Data Mines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters","project":"Superalgos","id":"d5234bd2-ef4e-4856-a6a0-ce7659653a48","savedPayload":{"position":{"x":14648.352187356151,"y":28990.05301821844},"targetPosition":{"x":14635.871225686036,"y":10349.288271084537},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ecc1a524-de9b-4e73-8874-b99a7ea0402b","savedPayload":{"position":{"x":14635.871225686036,"y":10349.288271084537},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plugin File","name":"Alpha","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Alpha","project":"Superalgos","id":"9d9d6275-91e1-448d-b162-8069adf7f207","savedPayload":{"position":{"x":14658.262986317583,"y":19632.85151122931},"targetPosition":{"x":14810.468084630062,"y":10200.168466117855},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5b8a1d1e-59db-484c-8dfe-7d35f2aa8770","savedPayload":{"position":{"x":14810.468084630062,"y":10200.168466117855},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plugin File","name":"Sparta","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Sparta","project":"Superalgos","id":"449f1832-f5b8-4e7e-a010-d892d721d3bc","savedPayload":{"position":{"x":14665.067482786275,"y":37715.63150649338},"targetPosition":{"x":15039.37033286441,"y":10218.18346374989},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0486ca8b-855a-4295-ba63-6f63421b4a13","savedPayload":{"position":{"x":15039.37033286441,"y":10218.18346374989},"targetPosition":{"x":14903.173182942546,"y":10485.4854210064},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"cbc3d9be-5e59-45d8-bb0f-4ec82763691d","savedPayload":{"position":{"x":14903.173182942546,"y":10485.4854210064},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingMines":{"type":"Plugin Trading Mines","name":"New Plugin Trading Mines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters","project":"Superalgos","id":"ad1ce785-858f-4cfc-ba68-108b5e0c54d9","savedPayload":{"position":{"x":31037.217404066585,"y":10729.643045797242},"targetPosition":{"x":15481.28847788,"y":10418.13122451946},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8a64c00e-4f8c-49bf-b57d-4e2e388bae41","savedPayload":{"position":{"x":15481.28847788,"y":10418.13122451946},"targetPosition":{"x":15238.583379567515,"y":10594.466800207203},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8d881813-3ab9-4e8b-ab5a-48dedab2dd19","savedPayload":{"position":{"x":15238.583379567515,"y":10594.466800207203},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingSystems":{"type":"Plugin Trading Systems","name":"New Plugin Trading Systems","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Masters-Lightning-Strike","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Masters-Lightning-Strike","project":"Superalgos","id":"37ab4b0d-6bd8-46b6-9778-e193c32669a4","savedPayload":{"position":{"x":24926.365708673427,"y":19688.576468868458},"targetPosition":{"x":15481.28847788,"y":11123.473527270431},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"5fdcecee-8c8f-4e0f-b36b-81e9231970a6","savedPayload":{"position":{"x":15481.28847788,"y":11123.473527270431},"targetPosition":{"x":15238.583379567515,"y":10947.137951582688},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3569d452-c593-4e54-a356-7ff8c6b519f3","savedPayload":{"position":{"x":15238.583379567515,"y":10947.137951582688},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"pluginTradingEngines":{"type":"Plugin Trading Engines","name":"New Plugin Trading Engines","project":"Superalgos","pluginFiles":[{"type":"Plugin File","name":"Low-Frequency","project":"Superalgos","pluginFilePosition":{"type":"Plugin File Position","name":"Low-Frequency","project":"Superalgos","id":"e117a2a4-09b3-4181-8455-e680de3bdeb3","savedPayload":{"position":{"x":31033.55093774257,"y":19568.049392142086},"targetPosition":{"x":14810.468084630062,"y":11341.436285672036},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e9270d67-4630-4ac9-91ca-1dec4fb5aa38","savedPayload":{"position":{"x":14810.468084630062,"y":11341.436285672036},"targetPosition":{"x":14903.173182942546,"y":11056.119330783491},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"87a28762-63d0-45f7-bd39-9dea436d8244","savedPayload":{"position":{"x":14903.173182942546,"y":11056.119330783491},"targetPosition":{"x":14995.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"c4e402d7-5228-408c-9d67-379d6ef40bae","savedPayload":{"position":{"x":14995.87828125503,"y":10770.802375894946},"targetPosition":{"x":14695.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"bfb0b514-3b9f-4e9a-85ca-d0ca714b09f6","savedPayload":{"position":{"x":14695.87828125503,"y":10770.802375894946},"targetPosition":{"x":14695.87828125503,"y":10770.802375894946},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Design Space","name":"My Design Space","project":"Superalgos","spaceStyle":{"type":"Space Style","name":"My Space Style","config":" {\n \"backgroundColor\": \"UI_COLOR.BLACK\",\n \"node\": {\n \"fontSize\": 16,\n \"imageSize\": 60,\n \"type\": {\n \"fontColor\": \"UI_COLOR.WHITE\"\n },\n \"name\": {\n \"fontColor\": \"UI_COLOR.WHITE\"\n },\n \"menuItem\": {\n \"backgroundColor\": \"UI_COLOR.BLACK\",\n \"fontColor\": \"UI_COLOR.WHITE\",\n \"fontSize\": 14,\n \"imageSize\": 14\n }\n }\n }","project":"Superalgos","id":"fad0e429-f7a7-4b62-a2a5-2ead29b8f695","savedPayload":{"position":{"x":25236.875,"y":8701.347826086958},"targetPosition":{"x":24936.875,"y":8701.347826086958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"spaceSettings":{"type":"Space Settings","name":"New Space Settings","config":"{\n \"node\": {\n \"distancePercentage\": 60,\n \"radiusPercentage\": 85,\n \"massPercentage\": 100,\n \"animationSteps\": 2, \n \"menuItem\": {\n \"widthPercentage\": 100,\n \"heightPercentage\": 60,\n \"radiusPercentage\": 90\n }\n },\n \"physics\": false\n}","project":"Superalgos","id":"05c9d6d5-24c4-4eec-9aca-9668d6486fdd","savedPayload":{"position":{"x":24636.875,"y":8701.347826086958},"targetPosition":{"x":24936.875,"y":8701.347826086958},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f8485ce5-67f3-4476-b9e2-80994e49c318","savedPayload":{"position":{"x":24940.875,"y":10745.347826086958},"targetPosition":{"x":24940.875,"y":10745.347826086958},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"frame":{"position":{"x":255,"y":588.3125}}}},{"type":"Superalgos Project","name":"New Superalgos Project","project":"Superalgos","projectDefinition":{"type":"Project Definition","name":"Superalgos","config":"{\n \"codeName\": \"Superalgos\"\n}","project":"Superalgos","id":"a2a04e12-604e-43f8-a986-1b8ca3b043cb","savedPayload":{"position":{"x":19378,"y":10727.5},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"spaces":{"type":"Spaces","name":"New Spaces","project":"Superalgos","id":"4d0ee814-4e48-4688-9cc5-7ee03de5192b","savedPayload":{"position":{"x":18810.69804274349,"y":10863.697149921863},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"trading":{"type":"Trading","name":"New Trading","project":"Superalgos","id":"0dcf22f9-cec5-48b5-b6c1-eb93d75c0055","savedPayload":{"position":{"x":18778.92479988006,"y":10751.037728718353},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"otherHierarchies":{"type":"Other Hierarchies","name":"New Other Hierarchies","project":"Superalgos","id":"228d01b9-466f-4374-afdd-15fff0426fab","savedPayload":{"position":{"x":18786.289023880698,"y":10657.466390843229},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cf9f8b3b-77c6-43c6-b01f-95cf366a91f6","savedPayload":{"position":{"x":19078,"y":10727.5},"targetPosition":{"x":19078,"y":10727.5},"floatingObject":{"isPinned":true,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Tutorial","name":"Basic Education","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back to School!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Nodes Menu","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Arrangement Features","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Pins","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Start With the Menu","config":"{\n \"icon\": {\n \"name\": \"unpinned-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Start With the Menu\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"117e0e8d-77c2-4ee9-b29f-d82f7b6f6995","savedPayload":{"position":{"x":25490.027487270225,"y":39634.40851272507},"targetPosition":{"x":25536.957826782294,"y":39930.71501490362},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Session Base Asset","name":"","id":"fb252bd6-3e7d-49a0-9fc6-be392be5db5b"}}},{"type":"Tutorial Step","name":"Pinned Nodes Can't Dance","config":"{\n \"icon\": {\n \"name\": \"pinned-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Pinned Nodes Can't Dance\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"734c6647-9e74-4d72-a621-29e0ff3e0bd3","savedPayload":{"position":{"x":25606.991435939068,"y":39639.00403878431},"targetPosition":{"x":25536.957826782294,"y":39930.71501490362},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"c69e3a63-8d67-4e41-b16e-39a88a9776e3","savedPayload":{"position":{"x":25536.957826782294,"y":39930.71501490362},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Angle to Parent","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Mary Go Round","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-360-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Mary Go Round\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"836a107b-368d-4ef0-8a43-5daeefcb0fe2","savedPayload":{"position":{"x":25886.240655911173,"y":40433.23445084565},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"180 Degrees","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-180-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - 180 Degrees\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"d9f1b166-20de-4ee5-94f7-0f9f363a5a82","savedPayload":{"position":{"x":25941.41057881172,"y":40509.16933527975},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Node's Independence","config":"{\n \"icon\": {\n \"name\": \"set-angle-to-parent-node-to-90-degrees\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Node's Independence\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c941ec5d-dcf0-48d5-a67b-5ce312c70470","savedPayload":{"position":{"x":25970.41512373375,"y":40598.43614568955},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Free-range Nodes","config":"{\n \"icon\": {\n \"name\": \"remove-angle-to-parent-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Free-range Nodes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"1b8726e1-8fa5-4584-8906-5c084785f476","savedPayload":{"position":{"x":25970.41512373375,"y":40692.29682471368},"targetPosition":{"x":25674.10862155521,"y":40645.366485201615},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"0a6ecc28-5731-49a1-878d-c1d2656cbecc","savedPayload":{"position":{"x":25706.338469709655,"y":40006.12813587088},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Distance to Parent","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Controlling Distances","config":"{\n \"icon\": {\n \"name\": \"set-distance-to-parent-node-to-one\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Controlling Distances\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e1a511e3-e833-4dcb-882c-28517b6fbaa2","savedPayload":{"position":{"x":26046.281424608744,"y":39996.77620519132},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"Play With The Tape!","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Play With The Tape!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"9ea33644-954d-475a-b3a1-9bca07951e58","savedPayload":{"position":{"x":26092.48784824228,"y":40104.32456902345},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"How About The Hierarchy?","config":"{\n \"icon\": {\n \"name\": \"set-distance-to-parent-node-to-one-and-a-half\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How About The Hierarchy?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"88ef7405-4f63-42a7-b02c-19f52b8f7576","savedPayload":{"position":{"x":26094.020040291325,"y":40221.36873391642},"targetPosition":{"x":25799.043568022138,"y":40166.698076268774},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Network","name":"My Network","id":"3c165071-7558-4708-9999-8ffe71d346b1"}}}],"tutorialTopics":[],"id":"c02373f4-3bf5-4b99-8dce-a152af6ec770","savedPayload":{"position":{"x":25799.043568022138,"y":40166.698076268774},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Arrangement Style","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Arrangement Style","config":"{\n \"icon\": {\n \"name\": \"set-node-arrangement-to-concave\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Arrangement Style\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"b03d5c5f-0ee9-48bf-a164-ce60a23b163f","savedPayload":{"position":{"x":26079.560122587445,"y":40358.9456609292},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Shall We Improve This? ","config":"{\n \"icon\": {\n \"name\": \"set-node-arrangement-to-concave\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Shall We Improve This?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"90b822dd-2f06-4474-a728-3500f3a30af4","savedPayload":{"position":{"x":26053.726562387557,"y":40473.113569359586},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Freeze","config":"{\n \"icon\": {\n \"name\": \"freeze-structure-of-nodes\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Freeze!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"2e3e7d2f-35ba-4620-b62a-f18d55e30989","savedPayload":{"position":{"x":25986.169297802902,"y":40568.70488774053},"targetPosition":{"x":25779.662925094777,"y":40351.092576436844},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Design Space","name":"My Design Space","id":"f8485ce5-67f3-4476-b9e2-80994e49c318"}}}],"tutorialTopics":[],"id":"14dbd920-b2e0-4b8f-ae74-22d2a3077082","savedPayload":{"position":{"x":25779.662925094777,"y":40351.092576436844},"targetPosition":{"x":25505.599287801997,"y":40229.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"3f1d0740-00c0-4818-b256-3280bd99ae74","savedPayload":{"position":{"x":25505.599287801997,"y":40229.0715835141},"targetPosition":{"x":25245.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Productivity Tools","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Intro","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Talk Backups","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Talk Backups\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"561b5fd8-43dd-42cf-9230-c098ebc7e176","savedPayload":{"position":{"x":25851.150517837592,"y":40156.65592801336},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},{"type":"Tutorial Step","name":"Working With Versions","config":"{\n \"icon\": {\n \"name\": \"hand-drag\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Working With Versions\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e60db488-cf9d-4bb0-b1a8-0d66ef657613","savedPayload":{"position":{"x":25973.52309136077,"y":40210.04653605334},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Parameters","name":"New Parameters","id":"e79ab7df-ba40-46aa-abcd-63df8031a931"}}},{"type":"Tutorial Step","name":"Detaching and Attaching","config":"{\n \"icon\": {\n \"name\": \"detach-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Detaching and Attaching\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"ae239506-f063-4e2f-8933-9f44dcc40fe2","savedPayload":{"position":{"x":26060.6116537401,"y":40311.245281501426},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Attaching The Backup","config":"{\n \"icon\": {\n \"name\": \"mouse-right-click\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Attaching The Backup\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"cbdcbdcc-5f47-40a0-870c-ad71d0d12079","savedPayload":{"position":{"x":26095.16724712524,"y":40440.208511700446},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Detached Nodes Don't Count","config":"{\n \"icon\": {\n \"name\": \"detach-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Irrelevant Nodes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"60c572fe-8649-46eb-921e-4815fb9419b1","savedPayload":{"position":{"x":26070.34571244971,"y":40571.39347727926},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Nodes' Attaching Rules","config":"{\n \"icon\": {\n \"name\": \"help\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Nodes' Attaching Rules\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"14d77d4f-ae2a-41ca-bcf1-d60044ac45a8","savedPayload":{"position":{"x":25991.063259072154,"y":40678.81738692698},"targetPosition":{"x":25795.377035688718,"y":40451.425869983344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Parameters","name":"New Parameters","id":"e79ab7df-ba40-46aa-abcd-63df8031a931"}}}],"tutorialTopics":[],"id":"c63ac428-2adf-4189-8560-5129c15ea793","savedPayload":{"position":{"x":25795.377035688718,"y":40451.425869983344},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"References","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dealing with References","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Dealing with References\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"References\"\n }\n }\n}","project":"Superalgos","id":"2733bece-0fd3-4846-9f88-8a95bf4f96f8","savedPayload":{"position":{"x":26003.4129110247,"y":40496.44315481149},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Let's See Some References","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's See Some References\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"775cc223-54d4-47e4-9863-a44e09dc2ff4","savedPayload":{"position":{"x":26055.18465682405,"y":40601.425869983344},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}},{"type":"Tutorial Step","name":"Visualizing References","config":"{\n \"icon\": {\n \"name\": \"key-r\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Visualizing References\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"5b81ad17-e34c-4eed-98f5-d45a84d6f812","savedPayload":{"position":{"x":26062.840367349472,"y":40718.22944118012},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Establishing References","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Establishing References\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"a5847b14-8e83-4f7f-bd1f-55c3ddc3a99b","savedPayload":{"position":{"x":26025.214530072662,"y":40829.0715835141},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System Reference","name":"Lightning Strike","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2"}}},{"type":"Tutorial Step","name":"Let's Get On With It!","config":"{\n \"icon\": {\n \"name\": \"mouse-right-click\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Get On With It!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Establish and Remove References\",\n \"anchor\": \"What If the Nodes Are Far Away or in Different Hierarchies?\"\n }\n }\n}","project":"Superalgos","id":"f4a434bf-93ac-4aae-9b1a-a5f3e510ed57","savedPayload":{"position":{"x":25948.035337639947,"y":40917.07758560147},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Is It Done?","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Is It Done?\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"6449893d-f990-47f3-97d1-089487e3c8b1","savedPayload":{"position":{"x":25843.052622468087,"y":40968.84933140082},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"One Last Point!","config":"{\n \"icon\": {\n \"name\": \"trading-system-reference\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - One Last Point!\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"ae02f7ce-5dc4-4014-b385-5405e915c4c1","savedPayload":{"position":{"x":25726.249051271316,"y":40976.50504192625},"targetPosition":{"x":25765.40690893733,"y":40679.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System Reference","name":"Lightning Strike","id":"c6397744-c7b6-4fad-92a0-6954f282c0c2"}}}],"tutorialTopics":[],"id":"e837dc7b-f8e0-4c01-b6f2-87898c505c30","savedPayload":{"position":{"x":25765.40690893733,"y":40679.0715835141},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Backups & Clones","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Back to Backups!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back to Backups!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Backups\"\n }\n }\n}","project":"Superalgos","id":"49f383cc-5720-4f22-a444-6a12709be5da","savedPayload":{"position":{"x":25880.678459744897,"y":40858.00718906684},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Hammering Backups Home","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Hammering Backups Home\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"823bae09-4875-4b2c-b461-62b016247779","savedPayload":{"position":{"x":25843.052622468087,"y":40968.84933140082},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Task","name":"Lightning Strike","id":"08222935-2499-4a3e-a927-4f5dfbc392df"}}},{"type":"Tutorial Step","name":"Back It Up Again!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Back It Up Again!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"8737b5cf-02ec-46d6-b6a3-705da85b00ce","savedPayload":{"position":{"x":25765.87343003537,"y":41056.855333488194},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Trading System","name":"Lightning Strike","id":"628b758d-ffff-445f-9d4f-8aa480a13db3"}}},{"type":"Tutorial Step","name":"One Last Backup!","config":"{\n \"icon\": {\n \"name\": \"backup-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - One Last Backup!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"41e890ee-f42a-4396-9493-8298445b94b6","savedPayload":{"position":{"x":25660.89071486351,"y":41108.627079287544},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Point","name":"End Upper Band","id":"ff8660a3-65b0-4df3-b823-f0656537ea30"}}},{"type":"Tutorial Step","name":"No Need to Memorize","config":"{\n \"icon\": {\n \"name\": \"docs-warning-style\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - No Need to Memorize\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"d14e808a-d408-455b-be7b-0feb0c862662","savedPayload":{"position":{"x":25544.08714366674,"y":41116.28278981297},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"What About Clones?","config":"{\n \"icon\": {\n \"name\": \"clone-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - What About Clones?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Clones\"\n }\n }\n}","project":"Superalgos","id":"7942b504-e00b-4d78-b4a9-defd17ac6e08","savedPayload":{"position":{"x":25433.245001332754,"y":41078.656952536156},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Only Share Shares!","config":"{\n \"icon\": {\n \"name\": \"share-entity\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Only Share Shares!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Shares\"\n }\n }\n}","project":"Superalgos","id":"39e09d3f-db3f-4961-9e32-915ba513a9a6","savedPayload":{"position":{"x":25345.238999245383,"y":41001.47776010344},"targetPosition":{"x":25583.245001332754,"y":40818.84933140082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"974c84fb-0112-4a8b-9f53-6d057b22a073","savedPayload":{"position":{"x":25583.245001332754,"y":40818.84933140082},"targetPosition":{"x":25505.599287801997,"y":40529.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"id":"338435fb-8de8-47e5-a51c-891399879226","savedPayload":{"position":{"x":25505.599287801997,"y":40529.0715835141},"targetPosition":{"x":25245.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"22c3e696-b371-48f9-814b-74a883ba6e7c","savedPayload":{"position":{"x":25245.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Workspaces","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Working with Workspaces","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Working with Workspaces\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Workspaces\"\n }\n }\n}","project":"Superalgos","id":"cd7b285d-22bf-4b30-82c1-4aade52c9dfe","savedPayload":{"position":{"x":25385.569414553385,"y":40716.52491818019},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Your Workspace vs Plugins","config":"{\n \"icon\": {\n \"name\": \"plugins\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Your Workspace vs Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Plugin Workspaces\"\n }\n }\n}","project":"Superalgos","id":"fa5f23d3-3a4b-4b29-9e16-f9d251678272","savedPayload":{"position":{"x":25245.791666666664,"y":40898.68682578477},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"The Current Workspace","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - The Current Workspace\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"78deb6f1-5589-4b91-ad96-d4397fafd6fd","savedPayload":{"position":{"x":25018.145953135907,"y":40928.656952536156},"targetPosition":{"x":25095.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Workspace","name":"Basic Education","id":"979bbac5-358b-427c-95d6-2b1df435d74e"}}}],"tutorialTopics":[],"id":"ad149fde-4bf0-4b26-b4a5-809fc8ba62e1","savedPayload":{"position":{"x":25095.791666666664,"y":40638.879204649435},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Plugins","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Let's Talk Plugins","config":"{\n \"icon\": {\n \"name\": \"plugins\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Let's Talk Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"366bcfde-71f9-4173-a80f-8fd4f5d7abcf","savedPayload":{"position":{"x":24978.42009536928,"y":40876.885206736806},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugins","name":"New Plugins","id":"bfb0b514-3b9f-4e9a-85ca-d0ca714b09f6"}}},{"type":"Tutorial Step","name":"How Plugins Work","config":"{\n \"icon\": {\n \"name\": \"expand-structure-of-nodes\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How Plugins Work\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"3e106105-19ca-4a7d-8915-c2ea46d92cec","savedPayload":{"position":{"x":24873.43738019742,"y":40928.656952536156},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Positioning Plugins","config":"{\n \"icon\": {\n \"name\": \"plugin-file-position\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Positioning Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"298ab522-ebbc-4b94-8fca-bce27208f8a2","savedPayload":{"position":{"x":24756.63380900065,"y":40936.31266306158},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugin File Position","name":"Masters-Lightning-Strike","id":"37ab4b0d-6bd8-46b6-9778-e193c32669a4"}}},{"type":"Tutorial Step","name":"Placing Plugins","config":"{\n \"icon\": {\n \"name\": \"plugin-trading-systems\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Placing Plugins\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"89958980-e536-414d-a55b-25149b6ebca2","savedPayload":{"position":{"x":24645.791666666664,"y":40898.68682578477},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Plugin Trading Systems","name":"New Plugin Trading Systems","id":"3569d452-c593-4e54-a356-7ff8c6b519f3"}}},{"type":"Tutorial Step","name":"Non-Persistence of Changes","config":"{\n \"icon\": {\n \"name\": \"bullet-error\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Non-Persistence of Changes\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"2658f4f8-46df-4a83-9a39-6327553ba244","savedPayload":{"position":{"x":24557.785664579293,"y":40821.50763335205},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Starting From a Plugin","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Starting From a Plugin\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"286d6e2a-0020-4461-98e4-974315326ddd","savedPayload":{"position":{"x":24506.013918779943,"y":40716.52491818019},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Improving a Plugin","config":"{\n \"icon\": {\n \"name\": \"sensor-bot\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Improving a Plugin\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"4a1b74f7-8ed5-4771-b0e0-3d1427a5510a","savedPayload":{"position":{"x":24498.35820825452,"y":40599.72134698342},"targetPosition":{"x":24795.791666666664,"y":40638.879204649435},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"73a666a2-268d-42d1-ac73-e7ae316542e7","savedPayload":{"position":{"x":24795.791666666664,"y":40638.879204649435},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Exchanges","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Talking Exchanges","config":"{\n \"icon\": {\n \"name\": \"crypto-exchange\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Talking Exchanges\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"Community Effort to Test Exchanges\"\n }\n }\n}","project":"Superalgos","id":"70ece243-3a2a-4b2a-9963-5044c11df654","savedPayload":{"position":{"x":24433.6596323107,"y":40591.203617870066},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Testing New Exchanges","config":"{\n \"icon\": {\n \"name\": \"crypto-exchange\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Testing New Exchanges\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"How to Test New Exchanges\"\n }\n }\n}","project":"Superalgos","id":"11a7025e-6b0b-4ac3-9994-e014b1980b08","savedPayload":{"position":{"x":24345.791666666664,"y":40379.0715835141},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"Clean Workspace","config":"{\n \"icon\": {\n \"name\": \"workspace\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Clean Workspace\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"57edeba5-84fb-4ae2-bbf8-c16f71c842c1","savedPayload":{"position":{"x":24433.6596323107,"y":40166.93954915814},"targetPosition":{"x":24645.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"3bba7ba9-7d4c-4d84-9c25-307f59bd7670","savedPayload":{"position":{"x":24645.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"Data","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dealing With Data","config":"{\n \"icon\": {\n \"name\": \"dataset-definition\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Dealing With Data\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"811af117-7a9f-4522-a391-f310fcab8167","savedPayload":{"position":{"x":24495.791666666664,"y":40119.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"About Other Markets","config":"{\n \"icon\": {\n \"name\": \"market\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - About Other Markets\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"7eb3bc72-7230-4c9a-bc7d-a568d3cc2465","savedPayload":{"position":{"x":24535.98404553133,"y":39969.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Exchange Markets","name":"New Exchange Markets","id":"2fd80894-900e-44ac-a1a7-56c14124f7a1"}}},{"type":"Tutorial Step","name":"Building Indicators","config":"{\n \"icon\": {\n \"name\": \"indicator-bot\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Building Indicators\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Topic\",\n \"type\": \"How to Build an Indicator - Video Series\"\n }\n }\n}","project":"Superalgos","id":"bbdede43-5ebe-4438-969e-e56fb8d36af7","savedPayload":{"position":{"x":24645.791666666664,"y":39859.456341243436},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"More Indicators?","config":"{\n \"icon\": {\n \"name\": \"data-mine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - More Indicators?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Book\",\n \"type\": \"Community Data Mines\"\n }\n }\n}","project":"Superalgos","id":"fd066dc6-57fb-4121-b8e7-1edc06bdf3a0","savedPayload":{"position":{"x":24795.791666666664,"y":39819.26396237877},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Step","name":"How About Strategies?","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - How About Strategies?\"\n },\n \"controlDocs\": {\n \"panel\": \"Open\",\n \"closeTutorialEditor\": true,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c18673fd-a8cf-4aba-b89b-d38d96991c82","savedPayload":{"position":{"x":24945.791666666664,"y":39859.456341243436},"targetPosition":{"x":24795.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"tutorialTopics":[],"id":"2c2b7b0c-de6e-480d-93d2-27bbb74b972b","savedPayload":{"position":{"x":24795.791666666664,"y":40119.26396237877},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}},{"type":"Tutorial Topic","name":"End","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Your Graduation","config":"{\n \"icon\": {\n \"name\": \"trading-strategy\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Tutorial Step - Your Graduation\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"2c47bc65-09a1-4576-a69c-990e47930ac5","savedPayload":{"position":{"x":25245.791666666664,"y":39859.456341243436},"targetPosition":{"x":25095.791666666664,"y":40119.26396237877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"},"referenceParent":{"type":"Tutorial","name":"Contribute to Superalgos","id":"a8711464-9e92-4e16-9622-a1b499a856ca"}}}],"tutorialTopics":[],"id":"0f058d80-353d-4073-8b41-805938e1551e","savedPayload":{"position":{"x":25095.791666666664,"y":40119.26396237877},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Reset"}}}],"id":"987e20ec-bf08-488c-92ec-7ef6e8b79ef8","savedPayload":{"position":{"x":24945.791666666664,"y":40379.0715835141},"targetPosition":{"x":24945.791666666664,"y":40379.0715835141},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial","name":"Setting up a New Chart","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Introduction\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Getting Started","config":"{\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Before we begin","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Before We Begin\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c8304d44-191c-49c8-a982-88a5ea42b395","savedPayload":{"position":{"x":19758.164424312257,"y":40103.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Charts without Tears","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Charts without Tears\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"a2d5c58d-1aa9-4958-9aca-0e5fcc806e2f","savedPayload":{"position":{"x":20058.164424312257,"y":40403.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Charting Space","name":"New Charting Space","id":"21d2ec55-9e56-4652-8e96-c7e451262c36"}}},{"type":"Tutorial Step","name":"Looking for a quick fix?","config":"{\n \"icon\": {\n \"name\": \"tutorial\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Looking for a quick fix?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"d9407975-f8f8-42fe-b4c4-f0589471cdf8","savedPayload":{"position":{"x":19758.164424312257,"y":40703.79490168751},"targetPosition":{"x":19758.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Network Node","name":"My Computer","id":"e452cf65-2b2b-44f2-9e67-bdd9d3c008e4"}}}],"tutorialTopics":[],"id":"c30627fc-e01f-48bd-8347-99c1b13b0088","savedPayload":{"position":{"x":19758.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Dashboards and Time Machines","config":"{\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Dashing Dashboards","config":"{\n \"icon\": {\n \"name\": \"dashboard\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Dashing Dashboards\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"e902be8c-fe3e-463a-b429-1dec70cb12b4","savedPayload":{"position":{"x":19906.52099292274,"y":40694.961061803144},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Charting Space","name":"New Charting Space","id":"21d2ec55-9e56-4652-8e96-c7e451262c36"}}},{"type":"Tutorial Step","name":"Dashboards in the Future","config":"{\n \"icon\": {\n \"name\": \"under-construction\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Dashboards in the Future\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"56913752-cbf6-4405-a889-1f9dc22f0f06","savedPayload":{"position":{"x":19831.107871955475,"y":40864.341704730505},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Time Machines hold it all together","config":"{\n \"icon\": {\n \"name\": \"time-machine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Left\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Time Machines Hold It all Together\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"Node\",\n \"type\": \"Time Machine\"\n }\n }\n}","project":"Superalgos","id":"fa55dca7-9a95-4e4c-a3c1-571d1aac5ebf","savedPayload":{"position":{"x":19670.537931557585,"y":40957.04680304299},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Keep it in one place","config":"{\n \"icon\": {\n \"name\": \"time-machine\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Keep It in One Place\"\n },\n \"controlDocs\": {\n \"panel\": \"Close\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"da032cf6-441b-4a53-a968-49f97c0a1c5b","savedPayload":{"position":{"x":19486.14343138952,"y":40937.66616011563},"targetPosition":{"x":19608.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Dashboard","name":"Testing Environment My Computer","id":"885265c2-ebb1-4283-a617-34a88780276d"}}}],"tutorialTopics":[],"id":"c8d6c07d-70c6-4999-b77b-155f5bf07dac","savedPayload":{"position":{"x":19608.164424312257,"y":40663.60252282285},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Your first Custom Chart","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Add the Chart","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Without Further Ado","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Without Further Ado\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"ea3312d6-88fc-4e7a-9ae5-9620e3bddfdd","savedPayload":{"position":{"x":19645.617758978347,"y":41103.38027070957},"targetPosition":{"x":19385.810137843015,"y":40953.38027070957},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Add a Timeline Chart","config":"{\n \"icon\": {\n \"name\": \"timeline-chart\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Add a Timeline Chart\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"db25291f-ef20-4cc9-8bfe-a477ad73d1d4","savedPayload":{"position":{"x":19463.455851373772,"y":41243.15801859629},"targetPosition":{"x":19385.810137843015,"y":40953.38027070957},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Why is it blank?","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Why is It Blank?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"a2131ede-c79b-4313-bd85-40fbd29287e7","savedPayload":{"position":{"x":19235.810137843015,"y":41213.1878918449},"targetPosition":{"x":19385.810137843015,"y":40953.38027070957},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}}],"tutorialTopics":[],"id":"f46dff3b-4bc8-46f0-a581-a8bf72c7f1e2","savedPayload":{"position":{"x":19385.810137843015,"y":40953.38027070957},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Managing Layers","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"The Chart of many talents","config":"{\n \"icon\": {\n \"name\": \"timeline-chart\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - The Chart of many Talents\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c0c76521-31f9-474a-862e-40afc6507f9d","savedPayload":{"position":{"x":19158.164424312257,"y":41223.41014395818},"targetPosition":{"x":19158.164424312257,"y":40923.41014395818},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Herding Layers","config":"{\n \"icon\": {\n \"name\": \"layer-manager\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Herding Layers\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"426ca9c5-6476-4c7f-bb34-af88b41de96e","savedPayload":{"position":{"x":18898.356803176925,"y":41073.41014395818},"targetPosition":{"x":19158.164424312257,"y":40923.41014395818},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}}],"tutorialTopics":[],"id":"875b6687-2c74-4dff-9f62-96c342298b59","savedPayload":{"position":{"x":19158.164424312257,"y":40923.41014395818},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Working with Data Storage","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Your data treasure trove","config":"{\n \"icon\": {\n \"name\": \"data-storage\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Your Data Treasure Trove\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"8ef69b83-1314-4f88-bfbb-fa4ae7aaf4c9","savedPayload":{"position":{"x":18868.386676425536,"y":41001.05585748894},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Data Storage","name":"New Data Storage","id":"e2697759-6038-4943-b90c-5a68651ff9a8"}}},{"type":"Tutorial Step","name":"Follow the Tree!","config":"{\n \"icon\": {\n \"name\": \"data-mines-data\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Follow the Tree!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"57ee6e8b-b8b4-4d79-b0b6-e80e9bbff001","savedPayload":{"position":{"x":18728.608928538815,"y":40818.89394988436},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Data Mines Data","name":"New Data Mines Data","id":"32e7c122-fa5a-4d00-9d71-d54e890e32de"}}},{"type":"Tutorial Step","name":"The data you want to see","config":"{\n \"icon\": {\n \"name\": \"data-storage\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - The Data You Want to See\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"b12414e1-02e3-4b84-abf1-c56eef5ccc3a","savedPayload":{"position":{"x":18758.579055290204,"y":40591.248236353604},"targetPosition":{"x":19018.386676425536,"y":40741.248236353604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Market Data Products","name":"Binanceus BTC/USDT","id":"6d7273da-5366-4fe3-9749-e643038abd7a"}}}],"tutorialTopics":[],"id":"ca9d3427-37c7-4559-a1ac-6004aa913562","savedPayload":{"position":{"x":19018.386676425536,"y":40741.248236353604},"targetPosition":{"x":19308.164424312257,"y":40663.60252282285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"1246dd21-45b1-4664-845f-ccea597a602e","savedPayload":{"position":{"x":19308.164424312257,"y":40663.60252282285},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Connecting to Data Mine Products","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Hooking up a Chart to Data Products","config":"{\n \"icon\": {\n \"name\": \"data-mine-products\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Hooking up a Chart to Data Products\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"cc2794e2-9140-4ca5-89d0-c812eee41f6d","savedPayload":{"position":{"x":18981.828848624515,"y":40646.5},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Dashboard","name":"Testing Environment My Computer","id":"885265c2-ebb1-4283-a617-34a88780276d"}}},{"type":"Tutorial Step","name":"Make the connection","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Make the Connection\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"4b347096-6bcd-45f3-b40d-6fcd6b3837eb","savedPayload":{"position":{"x":18872.847469423712,"y":40496.5},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Add the Layers","config":"{\n \"icon\": {\n \"name\": \"layer\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Add the Layers\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"f0411061-33a3-4f21-ad4e-670f8381f209","savedPayload":{"position":{"x":18872.847469423712,"y":40311.08980337503},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"It's Alive!","config":"{\n \"icon\": {\n \"name\": \"trading-system\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - It’s Alive!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"db11ee1d-bbf9-44e5-b99c-078510f6df25","savedPayload":{"position":{"x":18981.828848624515,"y":40161.08980337503},"targetPosition":{"x":19158.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"d4893496-189d-4fe8-a6b1-864dcd9a46b6","savedPayload":{"position":{"x":19158.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Connecting to Trading Mine Products","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[],"tutorialTopics":[{"type":"Tutorial Topic","name":"Connection One","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Hooking up a Chart to a Trading System","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Hooking up a Chart to a Trading System\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"cedbe86a-bf7b-4f1d-95dd-641198dc2146","savedPayload":{"position":{"x":18748.356803176925,"y":39993.98728055218},"targetPosition":{"x":19048.356803176925,"y":39993.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Connection one","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Connection One\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"68c45d99-618b-4371-8e93-b81d80d60dde","savedPayload":{"position":{"x":18898.356803176925,"y":39734.17965941685},"targetPosition":{"x":19048.356803176925,"y":39993.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Backtesting Session","name":"Lightning Strike","id":"ce648922-fef2-44e3-8d76-2bd7ab72a29f"}}}],"tutorialTopics":[],"id":"eb345160-093b-471a-9ddf-a30308e949a0","savedPayload":{"position":{"x":19018.386676425536,"y":40066.34156702142},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Connection Two","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Back to Data Storage","config":"{\n \"icon\": {\n \"name\": \"trading-mines-data\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Back to Data Storage\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"7b111d1d-1576-4438-abdd-bce97a4f2a47","savedPayload":{"position":{"x":18859.807855701776,"y":39852.82112043655},"targetPosition":{"x":19158.164424312257,"y":39884.17965941685},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Mines Data","name":"New Trading Mines Data","id":"e4e268f3-a677-4f90-90a1-d87244e647e5"}}},{"type":"Tutorial Step","name":"Another Timeline Chart","config":"{\n \"icon\": {\n \"name\": \"timeline-chart\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Another Timeline Chart\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"757c3d37-d943-4296-a0f2-2f3906d5bfc9","savedPayload":{"position":{"x":18935.22097666904,"y":39683.44047750919},"targetPosition":{"x":19158.164424312257,"y":39884.17965941685},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Connection two","config":"{\n \"icon\": {\n \"name\": \"delink-node\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Connection Two\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n },\n \"positionAtReferenceParent\": true\n}","project":"Superalgos","id":"c7b0d632-79d4-4c8b-a991-67298d30016f","savedPayload":{"position":{"x":19095.79091706693,"y":39590.7353791967},"targetPosition":{"x":19158.164424312257,"y":39884.17965941685},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Trading Session Reference","name":"Lightning Strike Backtesting Session","id":"a5de30a4-022e-4f8a-afd0-3eb6d8600ae8"}}},{"type":"Tutorial Step","name":"Don't Forget the Layers","config":"{\n \"icon\": {\n \"name\": \"layer\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Don’t Forget the Layers!\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"d78552fc-e294-4488-8fc3-bb4d4ea433f9","savedPayload":{"position":{"x":19280.185417234996,"y":39610.116022124064},"targetPosition":{"x":19158.164424312257,"y":39884.17965941685},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"cc15cee8-bdd3-4dca-a8d8-4c245aaf9498","savedPayload":{"position":{"x":19158.164424312257,"y":39884.17965941685},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Check the Chart","config":"{\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Check the Chart","config":"{\n \"icon\": {\n \"name\": \"chart-points\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Check the Chart\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"c8bebdf9-b4b5-4737-aeff-4a578389c810","savedPayload":{"position":{"x":19308.164424312257,"y":39564.43178477874},"targetPosition":{"x":19385.810137843015,"y":39854.20953266546},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"},"referenceParent":{"type":"Tutorial","name":"Setting up a New Chart","id":"f87a4d66-cd01-4712-8ec6-c232677c5547"}}},{"type":"Tutorial Step","name":"Not Seeing Anything?","config":"{\n \"icon\": {\n \"name\": \"bot-data-dependencies\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Right\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Not Seeing Anything?\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"80b65f5e-9b09-4427-b438-11bbc1afb412","savedPayload":{"position":{"x":19597.94217219898,"y":39642.077498309496},"targetPosition":{"x":19385.810137843015,"y":39854.20953266546},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"da19051b-3be2-492e-9733-4a21742d01bd","savedPayload":{"position":{"x":19385.810137843015,"y":39854.20953266546},"targetPosition":{"x":19308.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"ab24e3dc-c131-4a6d-a1a0-7df304237185","savedPayload":{"position":{"x":19308.164424312257,"y":40143.98728055218},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Topic","name":"Before I Go","config":"{\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"Next\"\n}","project":"Superalgos","tutorialSteps":[{"type":"Tutorial Step","name":"Easy as 1,2,3","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Easy as 1, 2, 3\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"88edf6e9-f780-4e0f-b031-cbe2bc2cfdaf","savedPayload":{"position":{"x":19608.164424312257,"y":39843.98728055218},"targetPosition":{"x":19608.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}},{"type":"Tutorial Step","name":"Before I Go","config":"{\n \"icon\": {\n \"name\": \"charting-space\",\n \"project\": \"Superalgos\"\n },\n \"position\": \"Center\",\n \"slider\": \"toTop\",\n \"pressButton\": \"\",\n \"docs\": {\n \"project\": \"Superalgos\",\n \"category\": \"Tutorial\",\n \"type\": \"Adding Charts - Before I Go\"\n },\n \"controlDocs\": {\n \"panel\": \"\",\n \"closeTutorialEditor\": false,\n \"page\": {\n \"project\": \"Superalgos\",\n \"category\": \"\",\n \"type\": \"\"\n }\n }\n}","project":"Superalgos","id":"72bd2fd9-4de6-4bd4-bc9d-a9fba53d9827","savedPayload":{"position":{"x":19867.97204544759,"y":39993.98728055218},"targetPosition":{"x":19608.164424312257,"y":40143.98728055218},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"tutorialTopics":[],"id":"0570a00c-734e-44fb-9761-44ccb63212ff","savedPayload":{"position":{"x":19608.164424312257,"y":40143.98728055218},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"tutorial":{"status":"Done"}}}],"id":"f87a4d66-cd01-4712-8ec6-c232677c5547","savedPayload":{"position":{"x":19458.164424312257,"y":40403.79490168751},"targetPosition":{"x":19458.164424312257,"y":40403.79490168751},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isPlaying":false,"isRunning":false},"tutorial":{"status":"Done"}}}]} \ No newline at end of file From b7ac28b5c72c31d822aa4adaf5f9b6ffa617f659 Mon Sep 17 00:00:00 2001 From: ssplatt Date: Thu, 8 Apr 2021 12:51:10 -0400 Subject: [PATCH 08/32] add password to api key config --- .../Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js index cdb03a1e7..8f959839a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js @@ -28,12 +28,14 @@ let key let secret let uid + let password if (TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference !== undefined) { if (TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference.referenceParent !== undefined) { key = TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference.referenceParent.config.codeName secret = TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference.referenceParent.config.secret uid = TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference.referenceParent.config.uid + password = TS.projects.superalgos.globals.taskConstants.TASK_NODE.keyReference.referenceParent.config.password } } const exchangeClass = ccxt[exchangeId] @@ -41,6 +43,7 @@ 'apiKey': key, 'secret': secret, 'uid': uid, + 'password': password, 'timeout': 30000, 'enableRateLimit': true, verbose: false, @@ -263,3 +266,4 @@ TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[ERROR] ' + message) } }; + From 2c01d2177a5b24877097261f6266616023cfc422 Mon Sep 17 00:00:00 2001 From: ssplatt Date: Thu, 8 Apr 2021 12:52:40 -0400 Subject: [PATCH 09/32] cleanup whitespace --- .../Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js index 8f959839a..fe6392225 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/ExchangeAPI.js @@ -266,4 +266,3 @@ TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[ERROR] ' + message) } }; - From a82959de1abc9919a9f55926be09918444354f03 Mon Sep 17 00:00:00 2001 From: Julian Molina Date: Thu, 8 Apr 2021 20:34:26 +0200 Subject: [PATCH 10/32] Notes on how to contribute tutorials --- Projects/Superalgos/Icons/Thumbs.db | Bin 6052864 -> 6075392 bytes ...algos-006-how-to-contribute-tutorials.json | 150 +++++++++++++----- 2 files changed, 112 insertions(+), 38 deletions(-) diff --git a/Projects/Superalgos/Icons/Thumbs.db b/Projects/Superalgos/Icons/Thumbs.db index 88827d9e046093ad2adc0a32ef16a7a11a8eae0d..2fc679ef35f4146ec233ba6c20c5fd7ffdf1fd09 100644 GIT binary patch delta 21922 zcmZVE1ymGY{4o4ky1Toj8|el`8U!gR0YMt11%~bvBori6K#&lmk)=agO1h;RVS#0N z=l6e}=e*B3&+PfYp53`QcfR-ToEz43iWatWhF0T-ftfj5k;ND3jnU|h0W*-wRxL0W zjr}JFgP=jsAs7%$2o?kzf&;;Y;6d;q1Q0?95rh~*0wINvHU5($*R3Fg(ZT>g8w~*N zp(C4A51k{{XNMd@0ilFYL8u`#5LyTwgdV~GVT3S2m?10>RtQ_8&kp;T3nA>k40ZnR zjI(`=IE-+dfd9L!3nPx$3nNYl7vuqi8^QzOZM-nz8+%6xtU?K5pi2J#6};Hvi@n(6 zhX_CfAwm#ghzLX!A_ftMNI)J!Bq34|X^0F&w((+5PR}U2TMt_#)<;nuq5x5ZC_$7V zDiBqO8blrP2=W-B0eJ$^glIvuAvzFUh#o{AVgNCOJcSrRj3Lh;CJyh+gcp=Lry`?0_)S~7v#MiFQ1GFXGF#g8};1vOm=I#n1V0uhCXLBt^v zkcSXSh!jK`A_I|y$U)>G3J^tz5=0sDUw*34e>I3YzGuZiTZjn~xIxBsdFBc;TBw)@oL_T#fk1!}c# z332PcOBF0CXJ!NqEhsPQjVlD6HN+{AWu;;2Uq+?L+mBiPZ4;9$t;|XL_p$l4W4krI z=t^^E+M@KmbX`7c82?5wrxsU)<})!gPz*s|Ey_|5#r?*9R`!^I%sPS}3%!Hw$LN?* zZ92(Yj`tYPzQts|GCRIst8r4IQt5TH_ij5^oNhUH(cmrGqcd$Lo5jTMl3b$0Vcr{| z7;?)M-`FvTHGM=C0keVa?(SwjR?6dESa+|g?q5>I?*fztx`Y9eT44epik|>IJ1m2c z9z59-!q?E#Gf4?2qj2C$Qcg$fOkbF-_Mp%)X&u-Mzu061neSU|!n zA{CpkNm!&MQJjgV?-4IDxhQ9P!98+%n;%J_dsc9j)wjcKTaFN-)ibNYhJRj62vaO*~1&(9kku6y$7T-r#$0Db9}G2`Cv- zi2Ri{GY@hsYYvRnD|$WV-AANO3)Pz2tpY6mY|oaN6*@eW9hSD4Ws*i}3lzrj@bR5f zWxtdE2Dq|DX-jsgD(T;z5UP+GJhuupP%@T0C+%=Y&&zABtzT$Er}B7MIVKhs)^e~pm=U6zmD$!w zt+>wI-JQ(M1(mG3VG&|(WECp#G&3aX_wngOyG~ow3kob?FZ1{B-%}Z1zIZ5e|M=*S zY%iwml_CJ91lz%BlLXy-b2{M9kSxj{fn6oW72&}pQ}L;{w>x3z*9?r+1y_lAB1s$S zzYO4kk;e5+1v^bYxPOVvOqOU9W-ifua>;E zRJ>m8X0&ZMo)DsZpj?R1f$;vrvl5-Wrgz8tio^ZnH&S1!qHO>c&(=Hz&0QP=HvG

H3DsdQD?ZW)lPSyvr~ZWKukB&_Hq6vz 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 SrDjk1-?W~j|Mcc7xc?6e?()F^ diff --git a/Projects/Superalgos/Schemas/Docs-Topics/contributing-to-superalgos-006-how-to-contribute-tutorials.json b/Projects/Superalgos/Schemas/Docs-Topics/contributing-to-superalgos-006-how-to-contribute-tutorials.json index 6264c6d42..b205fca85 100644 --- a/Projects/Superalgos/Schemas/Docs-Topics/contributing-to-superalgos-006-how-to-contribute-tutorials.json +++ b/Projects/Superalgos/Schemas/Docs-Topics/contributing-to-superalgos-006-how-to-contribute-tutorials.json @@ -117,55 +117,85 @@ "updated": 1617733117832 }, { - "style": "Subtitle", - "text": "One Call For Action Only" + "style": "Title", + "text": "Consistent Use of Space and Styles", + "updated": 1617904223037 }, { "style": "Text", - "text": "Each tutorial step should have a single call for action, that is, a single instruction that the user must carry out. This is the ideal case scenario. There may be exceptions, for example, when we ask the user to read a page in the Docs and do something else as the main instruction. ", - "updated": 1617720707328 + "text": "Use the different sections on the page and the different paragraph styles for consistent purposes. This helps users get accustomed to a certain format so that they know what to expect from each section of the page. Consistency in the way the information is delivered makes tutorials more usable!" + }, + { + "style": "Subtitle", + "text": "The Definition Box" + }, + { + "style": "Text", + "text": "The definition box is the space to the right of the icon, below the title. Use this space to introduce what the step is about, that is, to set up the story the step will tell, or to provide some basic context. ", + "updated": 1617902992986 + }, + { + "style": "Note", + "text": "To use the definition box correctly, explain the context in four to five lines. Avoid one or two lines or anything over five.", + "updated": 1617903200520 + }, + { + "style": "Subtitle", + "text": "The Call For Action" + }, + { + "style": "Text", + "text": "The most important section on any given step is the call for action, that is, the instruction that the user must follow to progress in the tutorial. Many times users redo tutorials or go back a few steps just to make sure they did everything right. ", + "updated": 1617904108044 + }, + { + "style": "Callout", + "text": "Always use the callout style — the one applied to this paragraph — for the call for action! Similarly, try to avoid using this style for anything else. If the particular step doesn't have a call for action, then the step should not feature this style at all!" + }, + { + "style": "Text", + "text": "Each tutorial step should have a single call for action, that is, a single instruction that the user must carry out. This is the ideal case scenario. There may be exceptions, for example, when we ask the user to read a page in the Docs and do something else as the main instruction.", + "updated": 1617904124728 }, { "style": "Success", "text": "In general terms and when possible, try to avoid giving the user more than one task on the same step. Instead, if you expect the user to perform several sequential actions, try to split the process into more than one step — as many as it takes.", - "updated": 1617721156206 + "updated": 1617904133804 + }, + { + "style": "Text", + "text": "In some cases, you may need the user to take a very simple action so that the main call for action may be delivered. In such cases, you may use the definition box to tell the user how to get ready to execute the call for action delivered later in the page." }, { "style": "Subtitle", - "text": "Consistent Use of Styles and Space", - "updated": 1617722131538 + "text": "Alternating Colors", + "updated": 1617906135945 }, { "style": "Text", - "text": "Use the different sections on the page and the different paragraph styles for consistent purposes. This helps users get accustomed to a certain format so that they know what to expect from each section of the page. Consistency in the way the information is delivered makes tutorials more usable!", - "updated": 1617733162806 + "text": "Colorful tutorial steps look great, while a white pages full of text feel too much like non-interactive documentation. Makes sure you break the monotony with the four different styles of boxes:", + "updated": 1617906625458 }, { - "style": "Text", - "text": "Consider the following:", - "updated": 1617722201424 + "style": "Success", + "text": "This is great for additional tips." }, { - "style": "Text", - "text": "The definition box is the space to the right of the icon, below the title. Use this space to introduce what the step is about, that is, to set up the story the step will tell, or to provide some basic context.", - "updated": 1617721881227 + "style": "Note", + "text": "Use this every once in a while to break up otherwise large sections of plain text." }, { - "style": "Callout", - "text": "The most important section on any given step is the call for action, that is, the instruction that the user must follow to progress in the tutorial. Many times users redo tutorials or go back a few steps just to make sure they did everything right. Always use the callout style — the one applied to this paragraph — for the call for action! Similarly, try to avoid using this style for anything else. If the particular step doesn't have a call for action, then the step should not feature this style at all!", - "updated": 1617733181730 + "style": "Important", + "text": "Leave this box for the truly important stuff. Things you don't want users to overlook or forget.", + "updated": 1617906591147 }, { - "style": "Text", - "text": "In some cases, you may need the user to take a very simple action so that the main call for action may be delivered. In such cases, you may use the definition box to tell the user how to get ready to execute the call for action delivered later in the page.", - "updated": 1617722090611 + "style": "Warning", + "text": "And this one, save it for real warnings. Things that may represent a threat or risk.", + "updated": 1617906578635 }, { - "style": "Text", - "text": "Use the rest of the styes to develop the content." - }, - { - "style": "Subtitle", + "style": "Title", "text": "Use of Docs Pages" }, { @@ -184,7 +214,7 @@ "updated": 1617733203373 }, { - "style": "Subtitle", + "style": "Title", "text": "Interactivity", "updated": 1617724494717 }, @@ -214,7 +244,12 @@ "updated": 1617733297397 }, { - "style": "Subtitle", + "style": "List", + "text": "In some cases, the actions users take may have certain effects. Showing users the outcome of their actions immediately after completing a task has a great educational value. For example, if the user is setting up a new Time Machine in a tutorial about the Charting Space, show users how the time machine appears in the charting space immediately after creating it. If users then set up a Timeline Chart that references a particular Data Mine, show users how the new Timeline Chart appears within the Time Machine, and let them verify that the expected layer managers are there. Don't be afraid to go back and forth... that is the whole point after all!", + "updated": 1617905020985 + }, + { + "style": "Title", "text": "Tooltips", "updated": 1617731886888 }, @@ -233,7 +268,7 @@ "updated": 1617733407351 }, { - "style": "Subtitle", + "style": "Title", "text": "Naming of Nodes", "updated": 1617731585276 }, @@ -276,15 +311,6 @@ "text": "Here's a list of requirements that help tutorials be consistent in their look & feel:", "updated": 1617722868882 }, - { - "style": "List", - "text": "Always use proper title case for titles.", - "updated": 1617722923539 - }, - { - "style": "List", - "text": "Titles look best when they span a single line. Use two-line titles only if strictly necessary!" - }, { "style": "List", "text": "Always use an icon to illustrate the step. Sometimes the appropriate icon is the one corresponding to the node the user is working with. Other times you may use icons figuratively, playing with alternate meanings of what the drawing may represent." @@ -304,6 +330,54 @@ "text": "Do not set two consecutive paragraphs with the same style. The only exception is for bullet lists. Even the Docs Text Style is not formated to look good as consecutive paragraphs in the context of a tutorial (there is no padding between paragraphs).", "updated": 1617723650896 }, + { + "style": "Title", + "text": "Titles" + }, + { + "style": "Text", + "text": "Always use proper title case for titles. But, what exactly is proper title case? Let's agree to the standard propose in this blog post:", + "updated": 1617902503383 + }, + { + "style": "Link", + "text": "Capitalization of titles 101->www.grammarcheck.net/capitalization-in-titles-101/", + "updated": 1617902444077 + }, + { + "style": "Success", + "text": "Titles look best when they span a single line. Use two-line titles only if strictly necessary!", + "updated": 1617902549247 + }, + { + "style": "Subtitle", + "text": "Unique Identifiers", + "updated": 1617905396529 + }, + { + "style": "Important", + "text": "Remember that the title of a tutorial step is also the unique identifier of the corresponding Docs Page. This means that the system does not allow for duplicate titles. Avoid at all costs naming pages after single words or short phrases. Let's leave those unique names for particular cases that may merit the use of such special phrases." + }, + { + "style": "Text", + "text": "For the same reason, all titles should begin with the following fixed string of text:", + "updated": 1617905464492 + }, + { + "style": "Json", + "text": "Tutorial Step - ", + "updated": 1617905492001 + }, + { + "style": "Text", + "text": "The above helps reserve some phrases for contexts different than tutorials.", + "updated": 1617905844332 + }, + { + "style": "Success", + "text": "Don't worry! Your titles will not look ugly in the tutorial, as the system filters the prefix and doesn't show it in the tutorial window!", + "updated": 1617905922481 + }, { "style": "Title", "text": "Proper English", From bfc83b2e32d712fc79dfa275cb24032411bf65fc Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Thu, 8 Apr 2021 23:32:35 +0200 Subject: [PATCH 11/32] Coninbase Pro handling of cancelled orders --- ...rning-order-not-found-at-the-exchange.json | 49 +++++++++++++++ .../Low-Frequency-Trading/TradingOrders.js | 60 ++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/ts-lf-trading-bot-warnings-016-ts-lf-trading-bot-warning-order-not-found-at-the-exchange.json diff --git a/Projects/Superalgos/Schemas/Docs-Topics/ts-lf-trading-bot-warnings-016-ts-lf-trading-bot-warning-order-not-found-at-the-exchange.json b/Projects/Superalgos/Schemas/Docs-Topics/ts-lf-trading-bot-warnings-016-ts-lf-trading-bot-warning-order-not-found-at-the-exchange.json new file mode 100644 index 000000000..3eea20702 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/ts-lf-trading-bot-warnings-016-ts-lf-trading-bot-warning-order-not-found-at-the-exchange.json @@ -0,0 +1,49 @@ +{ + "topic": "TS LF Trading Bot Warnings", + "pageNumber": "15", + "type": "TS LF Trading Bot Warning - Order Not Found at the Exchange", + "definition": { + "text": "The exchange returned null while checking an order. This usually happens at exchanges like Coinbase Pro that after an order cancellation the exchange deletes the order instead of changing it's status to cancelled.", + "updated": 1611922128136 + }, + "paragraphs": [ + { + "style": "Success", + "text": "This is not an error and may be normal behavior. The trading bot created this warning to let you know that this happened so that you may keep track of all the details of the trade should you need to. This page provides information that should help you understand the context of the warning.", + "updated": 1611922148396 + }, + { + "style": "Warning", + "text": "Order Status Not Sync With Exchange" + }, + { + "style": "Title", + "text": "Context Info" + }, + { + "style": "Text", + "text": "Find below the values of variables relevant to the warning at the time the warning was created. They may prove of use to understand what happened." + }, + { + "style": "Placeholder", + "text": "contextInfo" + }, + { + "style": "Title", + "text": "Learn More" + }, + { + "style": "Text", + "text": "To learn more about this topic, please read the following page:" + }, + { + "style": "List", + "text": "Checking Exchange Events", + "updated": 1611921970650 + }, + { + "style": "List", + "text": "Syncing With the Exchange" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js index 94393fcd9..380a27253 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js @@ -641,10 +641,13 @@ exports.newSuperalgosBotModulesTradingOrders = function (processIndex) { let order = await exchangeAPIModuleObject.getOrder(tradingSystemOrder, tradingEngineOrder) + let message + let docs + if (order === undefined) { - const message = 'Order Status Not Sync With Exchange' - let docs = { + message = 'Order Status Not Sync With Exchange' + docs = { project: 'Superalgos', category: 'Topic', type: 'TS LF Trading Bot Warning - ' + message, @@ -661,6 +664,59 @@ exports.newSuperalgosBotModulesTradingOrders = function (processIndex) { return false } + if (order === null) { + /* + Some exchanges, like Coinbase Pro, deletes orders after being cancelled, and when we request information + about them, it returns null. We will interprate this as ORDER NOT FOUND. + */ + message = 'Order Not Found at the Exchange' + docs = { + project: 'Superalgos', + category: 'Topic', + type: 'TS LF Trading Bot Warning - ' + message, + placeholder: {} + } + + tradingSystem.addWarning( + [ + [tradingSystemOrder.id, tradingEngineOrder.id], + message, + docs + ] + ) + + /* Close this Order */ + tradingEngineOrder.status.value = 'Closed' + /* + We must be carefull here not to overide an already defined exitType. It can happen + for instance that the order was cancellerd from the but veryfing the cancellation + was not possible because of a connection to the exchange problem. In that case + the exit type was defined but the order was kept open until the verification could be done. + */ + if (tradingEngineOrder.exitType.value === tradingEngineOrder.exitType.config.initialValue) { + tradingEngineOrder.exitType.value = 'Not Found at the Exchange' + } + /* Initialize this */ + tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.closeOrder.value = 1 + + await updateEndsWithCycle(tradingEngineOrder) + + let message = "Order Closed" + let docs = { + project: 'Superalgos', + category: 'Topic', + type: 'TS LF Trading Bot Info - ' + message, + placeholder: {} + } + contextInfo = { + exitType: tradingEngineOrder.exitType.value + } + TS.projects.superalgos.utilities.docsFunctions.buildPlaceholder(docs, undefined, undefined, undefined, undefined, undefined, contextInfo) + + tradingSystem.addInfo([tradingSystemOrder.id, message, docs]) + return + } + const AT_EXCHANGE_STATUS = { OPEN: 'open', CLOSED: 'closed', From 367a47fe71770fcbf165478f8cb893b98ae2f965 Mon Sep 17 00:00:00 2001 From: ssplatt Date: Thu, 8 Apr 2021 22:44:18 -0400 Subject: [PATCH 12/32] update docs for coinbase pro api key password --- Projects/Superalgos/Schemas/AppSchema.json | 2 +- .../Docs-Nodes/exchange-account-key.json | 14 +++++++++- ...exchanges-010-coinbasepro-test-status.json | 26 ++++++++++++------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Projects/Superalgos/Schemas/AppSchema.json b/Projects/Superalgos/Schemas/AppSchema.json index 6eb0013a3..abc4f3569 100644 --- a/Projects/Superalgos/Schemas/AppSchema.json +++ b/Projects/Superalgos/Schemas/AppSchema.json @@ -15789,7 +15789,7 @@ } ], "initialValues": { -"config": "{ \n\"codeName\": \"DOUBLE_CLICK_ON_THIS_STRING_TO_SELECT_IT_XXX_DELETE_IT_AND_PASTE_YOUR_EXCHANGE_API_PUBLIC_KEY\",\n\"secret\": \"REPLACE_THIS_STRING_WITH_YOUR_API_KEY_SECRET\"\n,\n\"uid\": \"REPLACE_THIS_STRING_WITH_YOUR_UID_IF_NECESSARY\"\n}" }, +"config": "{ \n\"codeName\": \"DOUBLE_CLICK_ON_THIS_STRING_TO_SELECT_IT_XXX_DELETE_IT_AND_PASTE_YOUR_EXCHANGE_API_PUBLIC_KEY\",\n\"secret\": \"REPLACE_THIS_STRING_WITH_YOUR_API_KEY_SECRET\"\n,\n\"uid\": \"REPLACE_THIS_STRING_WITH_YOUR_UID_IF_NECESSARY\"\n,\n\"password\": \"REPLACE_THIS_STRING_WITH_YOUR_PASSWORD_IF_NECESSARY\"\n}" }, "addLeftIcons": true, "editors": { "config": true diff --git a/Projects/Superalgos/Schemas/Docs-Nodes/exchange-account-key.json b/Projects/Superalgos/Schemas/Docs-Nodes/exchange-account-key.json index 79e064c61..aea174f36 100644 --- a/Projects/Superalgos/Schemas/Docs-Nodes/exchange-account-key.json +++ b/Projects/Superalgos/Schemas/Docs-Nodes/exchange-account-key.json @@ -16,9 +16,21 @@ "style": "List", "text": "codeName is the name or label of your key, as supplied by the exchange." }, + { + "style": "List", + "text": "secret is the secret key supplied by the exchange." + }, + { + "style": "List", + "text": "uid is the uid supplied by the exchange. This is not required for all exchanges." + }, + { + "style": "List", + "text": "password is the password or passphrase supplied at the creation of the key and secret. This is not required for all exchanges." + }, { "style": "Warning", "text": "To keep your exchange keys safe, never share data structures you may download from the system, as downloads contain all information in the data structure, including personal information such as exchange keys. Use the share option on the menu instead. The share option strips sensitive information and outputs a file that is safe for sharing." } ] -} \ No newline at end of file +} diff --git a/Projects/Superalgos/Schemas/Docs-Topics/tested-exchanges-010-coinbasepro-test-status.json b/Projects/Superalgos/Schemas/Docs-Topics/tested-exchanges-010-coinbasepro-test-status.json index b85b8b9f9..114859374 100644 --- a/Projects/Superalgos/Schemas/Docs-Topics/tested-exchanges-010-coinbasepro-test-status.json +++ b/Projects/Superalgos/Schemas/Docs-Topics/tested-exchanges-010-coinbasepro-test-status.json @@ -14,18 +14,18 @@ }, { "style": "List", - "text": "1-min OHLCVs Capability: Yes. The ability to fetch historic data for backtesting purposes has not been fully verified.", - "updated": 1616005829277 + "text": "1-min OHLCVs Capability: Yes. Backtesting and Paper trading are functional. The data mining process is extremely slow when retrieving full history due to API limits but it is adequate for live trading purposes.", + "updated": 1617935711274 }, { "style": "List", - "text": "Market History: Unknown", - "updated": 1615453086807 + "text": "Market History: Full extent is unknown, however it is at least 2020-01-01.", + "updated": 1617935743856 }, { "style": "List", - "text": "Trading Capability: Unknown.The ability to run strategies in live-trading mode has not been verified.", - "updated": 1616005834904 + "text": "Trading Capability: Partial. With a proper key configuration placing orders is possible. Currently, closing orders is not fully functional, so all types of trading strategies may not be fully functional.", + "updated": 1617935811860 }, { "style": "List", @@ -34,16 +34,24 @@ }, { "style": "Title", - "text": "Configuration" + "text": "Exchange Configuration" }, { "style": "Json", "text": "{\n \"codeName\": \"coinbasepro\",\n \"API\": [\n {\n \"method\": \"fetch_ohlcv\",\n \"limit\": 300\n }\n ]\n}", - "updated": 1615453067170 + "updated": 1617935879109 + }, + { + "style": "Title", + "text": "API Key Configuration" + }, + { + "style": "Json", + "text": "{\n \"codeName\": \"APIKEY\",\n \"secret\": \"SECRETKEY\",\n \"password\": \"PASSPHRASE\"\n}" }, { "style": "Text", "text": "" } ] -} \ No newline at end of file +} From a3c1edaa7534e7cfd9211ba5cb59b3f639c58bad Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 11:58:07 +0200 Subject: [PATCH 13/32] Omega One Data Mine (yes, it will become a series of indicators) :) --- .../PNGs/Docs/indicators/arps-code-node.png | Bin 0 -> 44963 bytes .../Docs/indicators/arps-slow-arps-fast.png | Bin 0 -> 152554 bytes .../Docs/indicators/arps-user-defined.png | Bin 0 -> 36485 bytes .../average-vs-average-code-node.png | Bin 0 -> 41478 bytes .../average-vs-average-user-defined.png | Bin 0 -> 48645 bytes .../Docs/indicators/average-vs-average.png | Bin 0 -> 180000 bytes .../Docs/indicators/chaikin-oscillator.png | Bin 0 -> 65223 bytes ...-one-data-mine-001-omega-one-overview.json | 42 +++++ ...-one-data-mine-002-chaikin-oscillator.json | 73 ++++++++ ...one-data-mine-003-arps-slow-arps-fast.json | 131 +++++++++++++ ...-one-data-mine-004-average-vs-average.json | 173 ++++++++++++++++++ 11 files changed, 419 insertions(+) create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/arps-code-node.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/arps-slow-arps-fast.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/arps-user-defined.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-code-node.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-user-defined.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/average-vs-average.png create mode 100644 Projects/Superalgos/PNGs/Docs/indicators/chaikin-oscillator.png create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-001-omega-one-overview.json create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json diff --git a/Projects/Superalgos/PNGs/Docs/indicators/arps-code-node.png b/Projects/Superalgos/PNGs/Docs/indicators/arps-code-node.png new file mode 100644 index 0000000000000000000000000000000000000000..650dfcab1b96ff2178cbd3e7ef35f32ca5f7f8a0 GIT binary patch literal 44963 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

#SYwx8? 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/arps-slow-arps-fast.png b/Projects/Superalgos/PNGs/Docs/indicators/arps-slow-arps-fast.png new file mode 100644 index 0000000000000000000000000000000000000000..7a6f0726c9def09e8285e35024e4b760e055670b GIT binary patch literal 152554 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

t>#~N8DM&Sq&BXbOVkXm&S4?zj2S3Y0_O* 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�R7e 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/arps-user-defined.png b/Projects/Superalgos/PNGs/Docs/indicators/arps-user-defined.png new file mode 100644 index 0000000000000000000000000000000000000000..c3470a0b698126fa838480199b4085a7bcf75513 GIT binary patch literal 36485 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-code-node.png b/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-code-node.png new file mode 100644 index 0000000000000000000000000000000000000000..5bbc092ff93ef7b73724a7bbeac0a9b7cb17585c GIT binary patch literal 41478 zcmagG2UL?=*ENcwC{2z6BHaoI2qH~tKtNGMK#^WVnsgB9hKL9X(v>bG^ddd<5(LE1 zBfS^t9VsD@kZ^bKyyrXb_y6}^$8f0U=#%yAy~Xq$Z<%kvPBhanofJsrL)cSaS|xC~A3yfsBc8M%w;SfMUVGo_ zPE363;KIIayced*dfn)(wXf7dvcWId31ABO$F#-yV}E}4?fL)z@7}x{Cw)`uxn5%( z&Azwp^K^aFnh-Y#{yl=~=11_0LStT0A-|rV>C>VD@K^=dG(iIRAicwFLxbN;>F7s$KR>+uN&S&>?UY_7^trv2o!ehf^ zxX!1-r}kOH@z#!xkXoI3U*ctR8;FxVwC+bJd;4tbr*T(I?$fX7;OUWr0&A~({Fry2 zo)lR9N;4o1jLJUNaT(as_ESOY=DD{4|Sh=R#5>rGU zOB!2U*mvq0-cs+<@4_#@YH&G#pb8t&&wY^5q+pV1Fr%$(3?J#q*QSu=z3{2OlIaA&Lujb zf((CUs*9kP%n#$*s>z`s{zf0Tm?~?~iC}|Xio#pRo8v{Te{d`?(B+#~yRR+B$l4_y zR%*{N9DMFlD1EDpnf_W3x_oH-$XxW{jxt`pzn$)!oTLVvk&*P2>c39!MO=2`m&HI{ z+u;(+t)EH^@yC(}_ysge!vt<<+W$oO)oypmM8V-3Tm*24BxlWNWp1xs9#|f^=3V|y&Az#TY9x{hj(2U1x)y1S==FpA-WEhH$6Cc@XC5riXQQf* zePq6xTZ}0UTlVRFSJ-h=s|+4xNA-re^MAi=t2;yUs~Ls^*>Kq?%fO%&-+_nHrz9-* zXP)S9C7tETCBVIJ8IchB9i-WAp=m+4Z~IM4Rd;jIy$jl^H3 zmj4xncQ5-*s|nX#{doRH6pwm>wkKk!&=e96fuY14$8JAnmw#RP5H4T$-MlB18UKHa zpPMcqh8@k%V@hp$joxJ8_{YlZV!tx8u+$LFTUlGz%#{>`!6tSGW4Q(QFD8Pa7w$~fd4 zlpZVLFwzop!|=JpG5bkW9TPKiYgdxYcpVbE@ZGivc%MImJfGcQfg9Qf>L#k-a77dNvqBrP5taKa z0Q$6neDN3SW@l$Br<{H@2K1!g|DG8>a4pB$ z_3@ha63h1Vr(bm<-9Ms|QI3-+Xs0{bAt};j$r_qCDM<^Hc}CQacAAjMEz$IuXR-~Q*| z-|VD_o>;)Zh3mYrFON;JJJp`G5zs(n|4JXom-vWf^Cc;0VO&-Q@*QnT4a#hzWgcO2 z5C{b}aobruJ-b9lz~}h*`1LAO*8NXBDnCL#kt3VpoK*nSvNb85ci;43)YzCTQjSY! zh$Wo<<3bBQy1k>^Q}5_b7?L8hkD0Z{+%W!2(sjN=)zIsBbL%JG8t-r}ISX(ux16UG zJSM*f(zD;iZogQpc-~C2ztgLc@g(b!mRdnH3*WLFt2HM1hH%|Z)YlbPdg^CRDPTz_V<9ca1Qg=v0k? zv#l>#YZGOMQ&m2y!onTfq7oBVj;j(wa)@pcspVd9H>~Syt=IPDODR3ozC!(j3F3A! zJL}`4(Di;zZFH}Xl&wOJVmj=)$CsnB*Hd(-_Srb?jD-ErUv91|&k&1;nhROn2Rl3? zI*D*MAss|^?QRtQIz3}qCii;YuC{pqR8fs|FqnN&ME|%71_rNfShXuAmvdEaHq=sw zGL+*WFB5*M!eNvrARu6UJ7s+<4^pS80r6R%s2lBnb;^4DI-ZD|^f(5WMBVf79dH&& zj(LnW7|>kJ~7`%kB!)F_hz(LTj+BWD4U~VWLM1V!c%vN(;tP$e0~;bTT3ky z8HwzjSHB4!r=YkRI`v-s>w16-MxKyIDC(<+!3NQUh>UPGf@T&jtb4LY{`WUZEp9gd zJXdNezZ1dN3}HU#xSKAU?Zi%0P*Edl&mqETy+)8nyOeMjd341L)qVPsTAPE?uNJ57 zDA6zGVFK8OLRm$B$O)|>ts{iI1{5@{r3}`5uiOoBE=&ur!&I|5<0UP%M$n1sIWn>< zk1*A;hOu&XusSquq|DCPd71MQ1@bfnMTA%$gIz;4B&2t;dfDkyqJ#q*BcC^}c(e9* zBW;1Yq-8fl$jV@$2b4tIfYq>D5==Fg?DjXJ({_??S2qMhH2XTWYu$-I_sKQi@0X!d z-CT^}O3wuc(>m|6nqTD}d4XSIjotOrVI{~$c?duR_-k!6gmatlECWWq;}maB(~rHP zGIe&9rJonu>%I1U0EF3>EI4k*)!4=_b$vAtPN-Gi+aZ0FR?_lsel}THPa1Lfo=V&i z&GIep!xW6nALe~!FS8%77B6X?YKs;~>r&r{&o0cVAapOVNi6TLRCzGSIobx2ETXdrk+b`rLGWD6TWK zpd0D;+|e<)gL^B?zBVQFfKVl4F|%6O@l%-VL@>y@)FNbA*9Bz+`8xml`%?cB)~jf&Oi_B@<}nG?El|*MdXX<#Fz^#&TG5qJ>zCT&`bEk$ zvqpo#@A-j_{FX)Eg&-NG z`wpnx!0e08qn4c=zLxQXhQ(}`bM(jk-48RK^j)y+4Z(DveE-!VP(<7mIM^2S!S84P zrI}x|&4qN*f4Oa)h|?S+KDQR#6Hxn=@Knnzb%dbmiY$b?(Sxh7J@Rdes~t3leKB8s zS(&eTzjU>ZC(b;+dG9=GGlt!I!(X=re{CCFp~>VJ4jHGZ<EbQw>>Ia@0*lOl;kCf~Hke7LPoM_@@ZB(J)C?RJN`f zg8CbqtzN}w-l$9l6n_b?$d9Dm3wKZ4I1AjLg5p|HqkLH|VWtEdZ2J9Ou$rl7_bQxE zU{$TJ!Z`8!yP#_Q_P~IBE10D*C1@5zZ9rjI0R71)09Nh~78ol3ML*(JnB7cGoSqig>ZXo%P3Bj z>^>BqztIp5Bo3;f+KB99Y5l@l!1@n|vi;ILnu11kjjJoxf6UNtnCyrbH9y`Adc7KN z7Z(=`o1K=(E7wFtpPU!eyXb>kj~=h_Xa|s#!}xA~sXD>J+PWQ&U9lwWt~rKyZO`8a zcsCtN*j?Y`g}=VcE@2;$mzS6An)B?RSJ=<5uQPuIdIPLL@2XS@YCP$z4}R>IJv$)= z#0luH^L-VMZcF^hO-;}VMlvxmeLoRg=Yw-c{w1#0=R02Q_6fwBD#&SL+dWo%-bgOj zmoG14wzs!4OzVAx04m;WVt~AI+t_<>)MZBnlHA?4=R4OcDkhxlvBfyUkz=TcERO>GG0jn||MTB>C-8M z9{;9{A@S(K(!SOYV{IEIxA63w(tSjo3bUp_EjP|5=-t6QkO*??Y+}~a5MF&K(*?O<}HZY{*w9p(L00Ra0W_zo^n#86&tn?jZzXpi z&^&R6ZQJBwr1d?{jcx;3ziEJbFI81lImV<_^eNlGE!$(NSi{*2yn#hwY~uXO72S#? zhL1UIf6OsD=n>E|ul(yb1509xsqAT{V-(*|{A)-f6{=to%J(RLT|4djt%t!{dgf>S zfgZPy%(9nwc%Yy6WWqB!ke>iJ71E~jeby&Gf=dgRe~J97&ir8EEAc%&`*|rIzS~y( zC5;eJr#ccP##ap!9AZhbwsiCqA4yUzbj0aRIIq)1a?e3XFU7oUP;fDgkrg&5Z7~{n zNRA)Pw^OGCjVDr&XNb_x6=})!^YtR-^##+^Oorw5OUWxG)=5d(-19rh!6TW_(zRi0 zxZBLm#^hu_aY4pwYc|`JfqzZuMQ%|eq`pyRJ(%Wrf3?hp2qA{&b|BRo_JxO%O7$i7 z$rAEB4-e)iGOZ^60IP%?U<(No-Jq^t{c0)dXQp5^b$i4mrORu7n(A{WAkXv_5hce} zgm(n4gNkjkqZD^<;~vr*yQ~WC?P50f-VV}itFCB6k!Bx=6ldkg6?R0QUkIC}Fb>uwLjy#12@*NJpuMpd`U`Wly7eO2`xU6) zau?;k3{0J%)Usw>HYctXt?%Tu!?9HWYg}{zSksa5{NcWVC=+ol1A1DW*^1&q(cHp~ z=f@SxrZ$woM^+)X%)^NDeh)=|3w&he$qhx;OAt=!|BDd2fBgcV?HgTY96+y+l^UlY zY(}=GFhn-StrZzo@vPx(_P3j!49y7__~z%kf~ikDt@WGkcq`?YnKp^Hr0w`tD5w)x zX@ft3ENuQa)9^qCu?Sbme)}ug)XT$b;96Jpi7Eh-Bi-v*ccZSUrGvC5QV2Q-+CkG; zF`vRLQ4W7UGj%#9IW|Ed=r7@twJ3pev`qA%VPg7R7R&J&_9O-nhRP%T zpafi=$vFOBUGyK$>whx^2r<@icyx&F#Eot@FIu&o_MDURas5Y_nu7YjI(&+Z;ycO^ z0o9$+LXzTq<c{nJ^%ivNt^z zJL^tVL0kgLJIEh-RR5Hpe^D)b>OageiHfOcnzO__k*|LL6#1tOk8RVab>C=;Q zC;7)4n)B5Q;Z_lg#ekIi#bWxO|EJLQ;(s_5OVDyZHZl^l8_0_cdELqT5I5HU1omVA}1ghoqPjkFU}QNK!bAH z49-AEdo$THETE(VvY~(zSh6Jis=4fMLsG2a)_)rbh}?@B{))t<{vRQ%GmRk8`=xG; z$Tob_w28|Wr{90OM#N)3?QbvCJo~ujm6 zHd{Xrod3z7WF36;sQVl-ly;9nzr-TQ zPI!s@!J0@t@&%uhJH_EqD`g^n)Ms9AqS<=+@}z_8LxcSBkjJ!~j@R9TDZj z4;;Nukd+viXqH+6K0#bZ{HXW1uB24sFj{`!%q)d=r`&Oz-^m8}*Uo+(eU{WAQs00e|~W=JdvL&q2mt{|^C zH|P&xtP`=IYk&aFQO&ER>EkFs>BX%{|3HnAA9GLX!6991f`XF%%H+MLG6=^TOE3@B zGx9$j3kCJ{^~tQS#B%Y-F$x8IJ2@nI_(A0AnLlMbYE^ClkU>UoiRwe3Q$~)n-5V{{ zxbK%*?o%U62!Gs_P zL7ib3+gSjBdpuJDG!rq8lBBE9Y#;dP6|pGTh^|uq^(UE?)l{k8hpNV1Nl8gJKnowc zHd;|5k?)f@y|dikelp)+(53!hs~wCTAjDs(hqXJ!6L!vkFkL^`sNH_#;aj~F#?rFv zDiDDU-)^}QUO9*j(+51PPdFRfO4#ItoM?ZxR@&HVXH;0XJS7#K^Tv}E{1cD$fodwW zcQRg{h@HaryY?asDD9wmDJdw8y1O+V8!;f!w3ZE;2+*Dvbe8e6Q>S#^-~gVnEU*l% zR_%%}KlqjT<^8H@vhI<0yb&`y87w6wb<1u*5T^$dGOE0Jj^a_=&4wHOyLf!8+X{~; z+beO05wV{2aoWe|on$+OOttUWDk@ttGwGA(Hw(C(=`&1Z!iw_LnO7Kbiav8tt606b z=uXIyT;2kPlZP92P+Vi3Nd=$qTG@X4_PB@reYBWO&-asWq({Yu?v09v&<*$x>Y{O{ zf~%2x05dL+ykf0IWfd6LR4;S@FnCc8N_czrs&~juEoOD!UXHH`M?`pf&@;qPk(tu| z!8YcKVsfC4v?yk!P%XvnekpE@yUV7MnQmF^La)eyUq)Cyv`n2+RruoeNbTS*M29rk zgO(QkNlQm`X!ADKC@O>}$8u$bW1&8Ug~#SV=RQ_RBDKlf9Tj_5Dp49Q=i`1=8B1$o zDklj;EXwVUU~9|PIn@9nRltjYY@;B z?WoM}j5xBcR-%Lix(>5?#NFI7e-oZ3WE z<2N2Zsry@wA9j;f_B`O&QSFbUzMVNIcQ;~Ds#Fo`+F^Ud*F^9D=%Lw>(3bo#L>yPQ({!x7>p@tnW)bVo!KCYckt&+qgY| zu&b(tV$YaJhL;lx3lE_uC(|yIudGge_27z(>dpnl)T~zhtORo%%A<7jD#2u%cIopt zvW@;VuFlrX*ndk^Oj8gOWnEX1(zUxiSXZtLreqPBehKnt0v+(LK{APC^~>0VBf~ae zF#Hhhss8UljB}>kb;320m`|LHPM=I1lq|Vsy6tk^=PS(+7fQ`^2jeRvXx(t}o$a#5-x9d}(x2N;w7!uRrv~`M%1s zgK7+93R<2Ft`0HuXdRG{uslX_k$A&%R{PI6E;PvaTK)$P^c4TkNM3ABNOfi+nlpYcnyrmen8+$0yLwCsU??$ibbqhn+ zYJ(neh`x3q0T7}))`1^CO61^f-GM& zF$aRV>vab=a|~s!zUO`!aWEI|5oeZ~YiJE|UHyZUqaNM-{lwg`;v+R9@c>HLsl^=p z&U8mP`)W@bzOS_o4B~?Qu6WgNyT4wuF`apA`Y@D~l_w+^(kG_*dYhYDIn>UWGM$B7 z%pR*HmRGbD;SMjktqh2dw%;o1beXsACgq2RF4+YHEw?Du*NZ<$JtKGE?1e8BR$C+T zUyTqu;#ASxdtRBw9-jb^uZC=Srff0=TJf9Cwsq;D9f&N2#l;To))#+y0z-#=^({wN7kMEY}HyqKPSJ4Y$MD3u#Cp zHslU6DvUhBg|+BL=h_Z*6Undv7bBBSK2SGF}!MNXx_^y?7B>C$?R4I0RG^ zCJ^wLTKwKd>W>g~*$pRWxUi|G!<%7~Gk;D{4|Jucsi02*qafa}I*hdZiBPmMtR;6r z3YJTsdIwJi&ke_ASkCx&TGcw(YJkSpD~)U1TX)w+EkWZ};{59l z3!m*M7@MbOXSdu)8Q48W$-i2$4LX`Ysg+ga6*y!5ZiygtRU1HU6K(-j?Ye3bk8Pf( zSAEfhQ$4Zc9}Bp*o?iRIE~t8hvWZ6lV6_BjzlWpms2ME)-i};ode0EM)SFdq-2Pl=UIIvwU&`16t_LYN{`Ci%5%NNiag&+bVKHP)9?twl!csYWr zAA6{+wb9FXhKVpXC}bPr*_UG|c}r%qlJU_^!sny$yQ*{pqA-_ylSKuJ)dCKIse$iF z-ZwRO-UpI=_-qq}+y>rg0oJCgQ?mnzrglI>q1vZg<+YBSUb6mTRvtSa#fa0mttq=) ziLJzPD|pnqJH<$*Itf_Z9t<t4!dP~g9x6VQ%-|eXOdNvjR$R-^Z^Mnwv4N3_tN=fZrXRbr$EM?uT1aq>^l^Iq7| zw^H9X2o|ckeC{fb8sY-=`5N(PtQt!k(Lc}b&GG^<-q!mkgXCRakm(RscKvt);d*W_ z=HSwW5Hu`VChfbz=FA{h__ARP`^dq_$)G|8nC=;=otxkz{!BR0+*{EWz4R5z$GPh* zsG0g<-sK`k)M~%*Li&?&c#b-YsgSPN?eF~sxA!!4$?6=$eDy}d`^#`{n7dczF#6@% z61G!eGjYr#6(60^-UJKjcqp6CA)~?Dax^^Wgtb_=CQ4l4SKeWo7*RY=e~|e1{N9i^ zBmxG3WwG)Xn4*Sce_*PqRL@`z7YUj!O)9Zf@xcUZ3)Kd%*cRb4Qe&$O;0OaJ$Dtmx zqO(piq^?zSed4T*h~IRaZ}?s8_12X4+(O~I%be7V;gC&br0Ge~zv0G~{#N}LCPp5| z7vo*4iKoFJ?mMi+5NLbY7rMjH?>njQGy~v}vQxQ9xuu>3yB1pJSO7D#H-h0Cm?OT6Zjkk)X5zKsD#Al_$ zl4r?-Ho#OL6`^d!Fxh2379MXn@2NU$`4_Dpb<8ZXFKuTxC*ezM{pVjc*~J4Pr^iSWAFcLu*^W2w{9d^d z7UO=8Yi6fz_JWkdA!X_aM(*$+4x(lbNxB$o`J=x53dqtoPFYweLmlb1aP$Fp9@n@# zuw12ri0Nxh>4x_lk8_b28I8a&PgB$v3AyJ}zdf$3 zW7?t^*^>F*bGs-96-c2{_D6!rI)Oe<9nG1FgPbgLdF9Uig?m<$J+lFjmVNZ^Q+_fN zUK4bO50EYs9oZs%yJv-uhQ4oRw@0pLwNE|4eCFnS`65U3%%iXw(p^wm%RV#n86fG} zpF_j=LP^KRy&Y7@6D?cW70S?M8=9n^4z;EJ?+aLBKKH$L2sJSzh%3BOEp8qs@A z${PCSATpQ>?-QxEvKTcYSu{xZ8}Euq3v4ZXKlC$>6-$CO1ZcrBh3cn+vjjyuJDH zPJ_VXO78&HgXXkFxc~FxD%cH_M?5habW$QF^837xJ-aRE;fc_*uao8nNkvF=j5R#e zhD_bvi1gvpiGkL=pI%97E2AtuVm75oMHr`XCm8qkFB>eBp&g8QtPYg{AKwT@(&NNx z5codHRh{eHR>qX8iQXx6`YsI_CG(B&`^1n%_Jr7bNt&uUCZ0KYG~t7*5lzoW3J<)H zE%3Anj2ufZ@aM;)r2BvINysBm`y;tiwQ3#a2UPAnWTa^WpP6^B zR^wrsphSF@F2>h7o$r0Q@JJr^X8QCT{if5y7C?$ecBJaZWqb_5RD z{z=XI`7LcRot-ddM!o{FP6Cz+bWd7`z9^-Kag`N5uEYC37>|SmpC@m;=f0LGj2i3Y zFCAg*Ux?Q2WY2*~&k1Z}&XR|4s#pF7rI$iYyEO_wP&035V#EkMjX*}ARcY(>FmA82 z4kCV(4(BB2LtHafih1K4=DJf{W8WQbmRVnY5eB&Ah`+m?;yY~h`x~_^jC@_3SPi7p zWnkA?cG^sExQSUIe?KM*#w8@R_zamZduw@3SQoYF7$OAMi00bgPLqw4)U_SVxBjnZ zHpN(aoG=Om@qJDGzajmi~6BHmzB0mS|SA4&}076%hcp%w~;0&K#s3?sA1Qdb~ouqx;MI=>K*cT=kwtX5D&MFAzx985}z z|Mbr6JVt^LYvF~lP752PaMmcCj7u?%m&gmJX6z5#uX2ZRudpFr^Iy@FT}d##dY;eZ z(9V?uyc*Y!aBg9r-PK4=8F%FnE;$1>u@?~~e$THT!NmX>$ZGDP)DEmnS??Fz)Nvv& z`{GZh?J~(YwBEpBCbX}Zjl!|xunmlykqhyo&)+I*{2J+>7XjKKg?;T;h@sz~x!doD zK8l4;k_@Y=n>JF7h88TPRNH^_jOZ0x3{%k`hhtN>U z84B0`SaqW2`g#n(yccb`!Ce?eeeUVzr1u{HwgpP!W;uZ?;?c02+D;>)zV(~Oq(C<) zo&zukF}qLGln|(I-rPiU`1Y08cJ3+eAnKEh)J!Y~ z&=;R?d?MLU`I0@|xNuB(g=R4R27<7CECPqda z`fPG9XH~)K#^;l?=Uc%1!4kJVehV<^_hPjKzr*07rcj7uIS*?>`_ z&p|6MyamwaR|NzFmW}x1$XS%{Q`bW}$cJ`aGjyQ-%=dPh!v|4^`z$5DLmNuw+U!8f zdP|sL|Q(88?)&HZ$oqH1LH_gdF>IND|%V8YGLsU}AlV_$mc0|L+WtgP;9%GXh65E51(? zj3Nh!ht+f=((*vY^p7Nc?nyUJQ+6#6nb9q^@Bn^{a!%NPGVIoJFZC^#ksZD(=+IAa zW3T8hlj%WHV6dbL{Vz2R&_$X30xj%iVrk~3RI0c5+EN9Pp+UPrk_lo64Cz!2uN_tX zOk&e3tJJRBbSw|bZsa+{i9hl>>I?tOoj+@+oC?mxslmjpxqYSQzP7-V#;Ue0NKqN< zn{^Db&&b)R$Dhil`n4BW$a$=%#|K1AQMx8x&1EOS*ztGV|GUtJsSfum(d_UHElZmi zWHscbUEbE#orGMV3n#1N`QUA*nYfoDjja%s_E_6)m`=XH=h5}Od?}EFR2fK9!r7N8 zo2Teh7>>#SjW?$0UQ^8b0NPBC#i>Q! zgUs}YTa?XUNY-^S*p)^25-6G%JDb`0s3a}H+*<8UV#y+ppi&@RP^r&RA&l;wYb7?( zG&KfX@P;Tm3}#>&%z+MUCa*krmSI0Pip&B)G2;ac_x&kXSN!&#>LM12Y2mP*?8rZF zzX=-5t3bo`B>3aUaXFTc!NC@@Es>F^jFZ9qGBTs%lHD@C=6kN@Iy&dcr<2WAEm-wL z&xSqk_4&-iqD3pgfeXoPdea=U0b)-($$S%PA-SHqwe{ZcAm!%Q5QWWecr4KCt@P!X z|4$`THLs@=aPViY#_)^=h*()IC!&_6QUr(L=z1vk-j-dyXkynK-&`% z=)Y-Slxmjd_WD*4xZS^ZAC7L9ELJH!7@pq*fBkwJXsX_bA=*E?`9~L<{d#*}Qm@+* z^R(E)%QO^>_Tvzl{D0_*V{KU_$D4IY@>dHKHk)-#M8e7BgccbFq~CP%XC7C*X7u5g zLs2R*Z^rM{6MetuHIqc40)^snPLDWp3jJf*sT39`s_i!kK_DjsRJr~RmimO`g~WxwfmC1Hd_ z(ZDFxBUbn-t8wPorB!5+bHmP4yR>aKW z*Q0Z(7bc0DuOq*Rsz0eo5`@()=}E1`dCw0;r+{6nkB+uUnh4LiLdTo``h=iNvkZr# z#}|H331ri_iQd`zRru)BIL_z=;2weJ`PRVYlztqnD{o`@A6uRXP6?r_`u!s@soh}m zvhE>%uxo>>)|Bh@GIdrvV|aT~xGax{Y@hL+OIDHK=1a+SOF>*(VwF_nDWO*!c8b5} zKK*jr+tDrw|E8$#?0oneuV=NT${T#=rB=VTRliSNn8X?VZt{U`jkWj~5N83OZS3l( zx?Yp~jO+@sWcSN$P&XsHpI@4rtY+k`J7pH=4cO_nb6Uv?-N=01E7Sp|qtaPhxvL5; z8d=;{4tUDuP?#-K|HhW6ZR>dFQH$6{?za)ap6q#xJ#)^N0)g8ILCeGLl>)s=8<3WE zmM0*9prHip7vi>K7v5WZZ@MJ4{H(_5{<6ip^g)gAaGKLI;2?1y)_{gMlUce+Ceh?}^hfv~FM3&9yBdtPLN6OU5gmH6oa|zH-wsv(%5Om9P zPcvcVFiA4HBNa|g<-DKlFdFs}V`r*ZGs(HWpVc_zKX;MpBxN%~eVex( zMw-w`-x$`qlsXqdX`8r^@F8uvFQ-poGm(LMCF>eVcltM6#>^ZTN63GlvfsY7KOglCr@K|U-)F=-@n zWtM>{9|iJ<4OxBlh9(s!(?{TnDQ^g#kQ8|;sR!@|&=<9l_gxg9KE13N0*7eU;>Oa_ z8k-RPN+vgfYk_S_Y4(BkuJDqyx8D(l!ncQBb8q5HH}_xSM9_&2%qe^88yk{KCxZiq zyV*;~ne8muwRR(^-f_PRfX9hF>r49b1nSQ$0K{(Ul#&kY5Z_v`338VV0>BzlG!;Et z%TTeoB~U**29=V&h}lFXc4j+}rPXd_-dI}?VFh|V>>gS4aIL@kyMZ0vfJ}db&8bQk zz%XBCb|?JBZyTo<-<~{)nrHIptW|K?Rf0$mfM28^BcD~9Vl4mRwLFmD$^$Y+sRVQo zLuGclEEZmVse#5xG9K;@Y;iaAOOy>N9M_U7Z2KPosnL96IoL|8LgRbc)s`**<Z+5@$SGB}mT$b5gP@yY|rLZHW19ywT>*amVe zmA6$Od{vI$D!dU1Kw`(UM9CObVAz5j?(=y*yy+9PN$HD7pS%qZF#gcmXp+8b>iT=C z!HRojz;J6}>fbG&Pc=>6Q`mc?^{RxzuOT(l@-?&j(8` zzoJQftRE(#Ea;0q51RUmz$h{gfXG|DGhUSU7OLl>X6zw89E-=Jf1*K6AQh>P>J%7V z2a8^jgWZFIc7drvK?7*-M-w96a;4#cFzGr@6>~p!Pdn172o;!&ZvE*NjJ5i_L8|S zAB*wa{t}@B)L=m2cJ-V9m_QXekMoOaYqO>-+MN|nO4{3uU#N0r`#sZ}(WHfL3w_Ud zJy!Cz1$=+95IdsC%VjnQ+&1bcol()B0$^nB4;b0EjB|S}-SbxmL`fw3@^O_yIlYPz zZ`}IYI%9TtSu#*3mwA~-f1mUK6Z>_JTGrTx!9HApT9P}t)9 zdrZ153}vXX45I&jKN6ZmO1m5SS*jx0k}6o|&0@u@u<*SAtGTkZ5%zJ6I*hb}JC+8t zF%p8El9bK&jWvR63%4o}B*m?tF1!y&RqD^X3NPywvhH-xu)Z7*xP%1i%!@(fxzbb` zdtL}V8O2fwRIlpCLJZMaqVx^t=$ROew`6^G?Oihw4=h@d6@J0Y4QTO(HOkPLEGO}+k)ke$l+9zLuw4a|1Q2d<>Z z7bmTK4Mh{%10^cj1H+QWLcTlPa1tS$bhv;M2Fuy2dpj7bY)`Ew;+2gXtb3E6`nj}a znhF3gyDA03NFg+fJ#UAhH&h#-V}rrn?WVjLI~rgyHIqNU(OafYPtF^k&+~(qZMI~= zec71rcmvt@>&<2s$M|A-2Gl^W2IK}=neom6tfhwc6XegZ-uh0Kk$hE5;`)lD&w3bt zPO1Xz=hwK@Icvt=Ucq*UKG`AKfLD{P4hlxa0%h=LZ-;}y!9!GExx=W%)HlBZb+qBl zif?p`gY@2QbZ3cMRvjTU9kO4!7lmj^yI_?*&W8_pc_Q5RQTfEr9~|bR{evnv$yKi` ze^!3)4YC^b=?@T6npem*JEY0EAzhT&?Z*CBhH}d2xUY|0mvLWpeq}v> zHVtlidbD<`Q>J2d)!qZ5wBaW9x}&WvxKtqNdKLJ_1hSr0#+qIkOI#7DPTK++ zpz&1|*zN2Er03@IK~s3Fd&fs%)Zzpjg(_bmbYCn=w|fG1s&Mc6G#{h;wkO6aTmehB zvKezrbPUaX+Tf-2T%y@C$Mw88)HR2;60`58<}YlHX}A!VuU(c31)Dc4zHYB(iQs|} z56FW&Tc)~&lnFu+CE}w?PZ=-# zY@9p@lhO|sB6?YbbZYG0BIuVxvF;BMm01{&2-(5mMt6b3jo20A=rfK}8+oSEq%z)I z#p6))cIO-&6Qm|b3mClXB-g3%6M4C&g1i}*n6%grcC*w->DSk@>I+T51|QNf$$oi1 zkCv%@9uY&KY|z{#=vI1wyr z9m_!@1SJVa>c3NoHM&&gRjih%_Sg!sc-_cpP_6hH%pO=QPv8~V;3iv4c83U^gurHG zL$Krb=bQ}b)wE%<7kM6z{a(Iebs_t~NVgXlN?08tDk+;^;xi91=69N(glC(hJitHK zzD*95HW>-Q33?rJpRivf|KQ{4$z? zq~EP^3NFs0Go3ilM!%u42B=$Ae}YQj7cWnp^>msU+ie3h<G1$G;E5)jvOFkYjt=d+n#IJck`u;qEm}!7uRw0o(J54!%8--spvVx%x?!(Nr0S z*iuHXr@iCVPm6qeuU(3lTz6>&^amIv$GJle*C(nOy=2kfzou^kr}%wzuuM+=(Tzn% z@Vf1(*}$fPw9NcBY4WmMf@=lqiCpGz?1vNY*{*tHuR%?N&oDRX$m1>gij$$#Op>VW z0{gm*q&xvZu~E6n+5tg+P3`v_5oRX-ZGg|geHAQ3J}O;NB#{RZh$F39RB}Z_n=U!A zkCrm9=OI$B^@dcG)PC7d1E({wz#XrMSO=3iI%|zR*<9$r=R%8>Io*5M>#NQc9fEO; z{Z8O(FVqidg(}8e3y0VDaWx+36T#!R7$gf7OQ?e9q}PfkrSC43)q>dpr1|0kSCm5kPAlsEqp=3NEVKPr%Fowzm*_ z*qpAaS-GT}-zi^h*1k-rxrfhjP%n%cTN1qj1!53wL+LT|U9A8+UEqfrMy}~z^rxBB z?vjThZ4G2M)86rY?>*Vn1Hd?er=)?VttU%^8%WAq<=^w>F!4RIbG6cr+k>Af45m3v zJda!9rrwT`BfK3(Blj|NFGG{m3L>J%;m!_(b9{~tgO_Z_@+&-mfb1D!uX{ryl8kRF zU1lr*Ems1j#Nc~6!aCp($kv7(m>l1F@e|R4?M9p2&VryrSg#1^$*QLC1_Iv4 z+S;>?)|^hDWJa3HH9XTie7y)gEonbA)o4c?20FaK`2aufjV2&OXp@|LJ%fKyw8ntr z@|rzMUJ5%g33TiqS(Ug6;oXBfc+kDld+#h>0*l2FpdV8ivFeEXHIay#2kKV~ASwah zn{eLa5vdr9-QfVVNfP+Zm@4^+mE}72dJ^8w1G-bTQ@w&6B&QY0TG!MPV_VWeVemBefTXv!=h-ur8w}-D>bhDQ$I}y zakoGzXAxW8p4uc8^FEB5YE<1A`ujU*uApsH_ZQQ`s~5b-V*#-C^#&cA!U&oC(`Gl$ z%~OjZr_5OCl_+atygetw=ez#r=ncTKi0_XuPIi5oe2AM>LZGl^r)PUtR}APmY9x}H z#hoT(ZMsucI_$JrU~ym+bRh>L^kLb2*mFBy3!U3|lD6}&BC&uf9u|Eg~DI}3fPspi>Dy#YJVaKIY7(Q)c>6VOFr zHbDDNi>oaXZh`qW%n;2N{%C~2TbXX)PlWfvr3-K-AVC|Dn_}(j<6_r9N_-`H-j41f zm-nGE?B~qVP;r_e&044J_VIY|4H~i1GwMx0{&Wg14tS$jznBG7NVFx0>ERh()n99z z=6L;AXzRmG+nGdII1NR6$>w2Tb4c;r#Ho4@T^1Jp^MQwQUc`)zVUXP!PDaD-+SHoC z2Q!Z$1AQOFa@xgxiH~PpN&{nrKFB8l-GWzYVP)Y$;bD?wahR#^zNJNAx==5ms*!od zH3Oj;zbZYB-t3h1^s+fwQt=mg|0nyLZora#6AVzABClfprraolXsG14=S^Cd zqOMB$#93 z5l@qLhV9gwhD&f^xO{g#-AeI^gJu(|{Ox6u;8FTiuk)L$pieaz=3#LUv<0F}M!azQ zOXa$h)ziijKKj=8B7rq>!=mvz0;7M8=n`d}uK02j$BQq8COcS2OE-%#WIYAQRPLyP zOO%9}bNcqfjbJ6=%H?ui4%NZU@2~HS>Vcad?3l`0X(L|u#A35*Ry)vlj@5pBCdy|p zzwqr5FV)9IN-nRfM5#lUM16D;u!4@bQx5(K5Xk`m&(GxGmOX>}%C)`^k9`Nw^2TpH zxB84NJLxTu+dU>vx>nWVYCj$iq6lIgOW8B%)xcKurlkV$CZ|f`$;#>0lDNaz$wvV8TCl&GhJ56VQcFRI%L3)4d|8TM!p)OrI%@ z)akPL5TiYr0lroFTNPA6A;Ru^M9_UL>LQO`jl|h!&X6X|y!sd>Y`EIy+_`eoxQvvV zpV_qP3IBSp@eP6?oX6*AhpUyJxkR>zyi7-vL=3QXUx>-$H|GuNxJ+Fma<6DJQk=r< zVjnItctvMPRm{t-)1;*YN(xNW%*)u0y>S!=Dg= zO@`o;u1D4jzYFhdf)Y--X5gVobrcw?($q#$mgcdWgfg*-XDQe?t{hj>%HO@O7F}xn z>rt_uCiGQteI1LVS%uvg=p}CqY}n!$F*DVa#}*U53N`5;{lS_q+EGQAowelY2>Axn z2_)1WOBqe_f6fBM@X?F3xv1{>lAPN?(2?_$_)2oL+rMY=BG?8TtLUfWHhK5dcH);j2;~FvB?hZt6QQzHk==fFmfuh(pAL!y z6?=U&$I#uPt4S3AUFvyP*~0Xz_~4VcPLldc!K#s)ChXq(qbWa%HZw+KugjDy&dsM= z|2U~By_=JTsc@KY=IavKFMw+c$`&O4(T9?x;L(-vnD;4lHygs!&hYlcRiK79`&osY_uJl=?&QEkt( z-aWZaRbpnp9gSXH)Cv(9fj5ofKxzbC*8dYbn}0Z(=AW4O3&2!^9i_$8gb$uOACtR( z)yfmnkJZg%?Dd96L#~XCJX07fg2s??-ZD#gOdwo)IXMvnyBlE_T+iglB zMh&GkTmFd^-vx+cyz%IGq300m8bho*o5L%tapdmEpcXAetF*d{mW0m$OBgecbj1hm z10C#fviWS+txr0huZMJlmUXMxF00bn)SsAggEx*&2fOJFP-A6d+Q^U4I=Q>2L*$4VOq~WJjK*L#>TbaL5!n`w80=$d6W(Y(*eHf>y1^zFyXv5= zI;9;+j@2(r1hM{C*-b|+VT8e$r4LIn^oAf4Cp4!>sT|-xba~@P(n4HIWcYki9*Xb| zkPz-a*k82~AklW)W_;3+h~seSG?v8>g6IU}>$kUfwnakJX|dJkyQS-ZA~{k!^oTI1 z2MZN#bUN&3Z}Lo~i19v%k)*Whk16QIw~95AP*CF5m+u_W|CL)%BmC`iQeKqaC9V8g z%}@I&>3x=cykp1274{N`aAm+yj1zfpRU?n2Z5;5X6|Pm71X+GaiOYIUd>IKHLb0BCTlkx7TalEg5mR(%hPq-qi+Wi-EzT;Mnh8S@G7q|N0!z|A z+`W)}Xph|d^(qK?dLEaZmN90ZGym}xY9>dzB#3(REC_=}?5kysCU1)X^lA7bbr^2) zNsQ)cPr!YXyRT)NSFQFIen}otDF}c4ZTRiiJ_2rLZCt_X-7ZGcG+TIo!Wm8p~l;F4T{1nY^2KSD} z)LOrR#4OxlzBlgLV+qGvuL5f3_iYT)Xit}GEvLxIvdoZz+k1otz|8)CoHA-`HB%|L zROZKr605C9(0BXp?{C9q5;g5iem?(=q>PstVc`3HxqzQMtvP*<^%DnV)}CH5dJ3gW zQv>jVin8F`86R{IUK#lMF`o1RD!kq~tzp~dwr{AN>v0)m{kT%hIiGV|qzBnSrH zk4mIBstJgl`pVcFW^k%x0B#w7WoiOLkK~MLru_VfFUM#9B)o#+_*#5Rh4+|TTjOId zA*72y!*)Jj=R)NTX;c3f32r>ngA({W9VuyLUH;oRHAakZ7Rh$J(?{ydt~I+d=QP)Q zijBOf$gPsfJSVTSAMBV2pf}vHUt>C!p82-eA^WZb*>@aiqkrx_HUvWsom2^wTKK(F z`M_(rHjsdW=G`_0VBFIQgJ@5tJDaQQE{|9W9{ZkTK(k<+a0R)A*YI%F_;oVqmj4=R z6vsCotl`fl^}U}YXSpgFD{nh)m|xM-+o|R}m>%H2;)L1u(I0)-S7!a*99NaNH=QT^ zxb$Z!53Y-Zl*_AX?w{=VJ2kK66HMy;S>OZ_2qKmv5ISR)X=k~=uRzx13Fcb$esI5+ zbYJJ}bpct$L4y%dd2bTGHMr*2ZaV}DmKmw(WA0l zd?E6j!&-AqHYbFxsbZ8Fu{k0F#>j@fyNm?Q;) zP1ArUjstaTiC2xd>S);xw#x;cAT0?!0NbJzo8W3275{%N*BDqGX+>tY&6yZKUcDbV z=;`>?XY85$?T9x{!r?Dzm#l(cf2VV>=9=w)#xe}PU~s7ZvQh)a#jga+oyTPk?Q z6&rnG=TV{W?9ZKxlz`KP$H5BO3n^*G+a)|efDgV1kC+dRzr(0gN9Xy+h+T>nj5PAs z-ZV(T4gcf)1OHq4900JI--&jbD;auNk~JiXr)}+16o^J)WneoVie-jA|9`-!9&HsU z-#^1PhrRzm%kaH=eSYRMvo^AZ+Jt6aWczWvfGY#c*-1k4|Irdk#oYI^KLt@AN)@rF zC~szRlHc}5`ntLa#M^uO?~nRGEO;0Sqe7qOdf$?fB;8g6MMdRUK}F!mUve6D$$WKK za-EI5F|T4_2E=aSiw@ZzOU*%Rq`Tvjg_g-+S>gOWC{fG}lv+iBzD`;1Y*+SMU<7`7 zT@1y9n5#DW%&J|zx)t`>f@VF(t8RwJVY$|yCi%0 z1Q#}jdEi>d@G?cA&z~I`042X=qiF}E$KwhGo43HoFBA62Z%VE{t+Hz@;Cd~&Hv>vY zMtXR2afr@rhEuK+!|?i_dDmyl>a)LTj$(`jF(GX&EfIhOlkeYf zsEP^yvbwk2mJ=}<<9NZuHg*V%rm74Q{i2vJkbbjgFXBGaV_04BZaYF<*T&+DY8zvk z3%+G#!aM!CKrpH651)X5z~$o`A;}?1#N-Z~`?K`o#;tTtOT+U||70nBsCHE0MX4PW zR>wjPyC~s1K1)S}2`ruO)1utP4o~feH(y_~7y^IYC-s-T84`cgD?F z_N-^u;#-e)^?75i?(`cH1br#Isb4)ZhhM&rC}9mFE41Yt$>xTOOQeL`sFvzQ&}B>N zOv+CKVFe!$S*`uK9;UIZu4e!mKJ$|2tA!<5J;-1M=M<}aoQIQ6;#HOYJq+YIA3>eC zi2dcT-JN67X7|o7rh4om{V_RTQ0q8u@-%B7 z3UQ#L#Kmve82+hj}bAz*YjY-cD6B+)b)w$lW@=qm{>Ct#t zFe=m$YUf>_ml8w#CO*45x;d0pie5twV*U3Z_xWUy+VY`@H5?Z82oH7sfBwetWi_DB z0c;lepDY;^4$nwSUf&|KReBiYq9E$J^pC$ z1rEjWy4QxF8G*bkgyq}`YwYBSZjMXQNQn=S2ePdtkkk{rC8ZJM#nv}@mrjjTH<>Rv^U`y4iFJ3PRIyD8F$5VM!RgSVgD_r(!NQdgTYc z+a4^p!&3!m-#*Clbk zS*nBm(1ra-@&;YBg+)u`HOkoP{R~Zvx7I6=z5`$*Sr~v&YG-8@6f`C7Hzgz0yI%RIn^wR|v;GBdWomsdmZ0 zvajezyq1wsMkQ|Se{ibX7+3nL$#KlRf_u>99n|>OIdJv0LRZd}j17+-KqZ~jadqX= z9OU^%5HznrL?g@MV7#iH=HgtTm`uC)Whyq;kci-Mvc)|IkN7a?LQ9$v zrf&5n@i`~T&1?IH?C;-Sq1)?K82~10%2Ao+*jWu4wx#)MhBM#raYz>7t=l;)(j4Oq zK@T*jLfRNzw1IgirXnPvNz;>eMLk|kJ-A?9a=wJ)D@a{7(jXUQB0%n&97`GOqVy8v zHx@9tzRKjQ>dht(Cc73 z<=M2Uq-A@GpZJ4s=)BpYS+HACRBVK81B`602AF}uw!@vwZ0P5=xhvEp`4Pf0tHW-~4o&I%l>%59S)9TByGdE&5sqXa zetQHFZka&bnSt`Vt2V&5Mxqm&D$M{_%k&mil7v#Hmc9RbR;u-SdBb6ssH@v_c2#>b zY;NwGbs=rm$zvajdH4s;U4!Cb;n}{)KE_~^&?!Gta8#Ik-@XIeRn~|-QbhIRby2UZ z>FL+0)9S-4ZDN)ygN>CFePT`v0(dLL)G+8Mr*K=e0zB)$DW}-+$S1YHH_^7vekHL_ zS1hRuk?83h5Hqx-Gyw4sjU&;N!Jq|9I#bmm59OaJN9j|9#s~EkorV5Z7*|(ic-GJb zDNFA>hzUM;t+MCQ4btNib?x3f($cls;FmxwXttmDL;xA%QhzR@HSv-=YRjr|>~*%q zU)zojD+eVaZF|#h*idB^4nt>W-p(yreX93`Mxg%et83LEV}ILj!Tz2PP*V^D2`^h1#2t|X>K%z}ZWI!IU7TMSin137uylpx6U6bu-6T@eYgNw$yQdnqqhCtb&f zDJVq_D)Lh_QriC2k{^_7tE=-wbv1{r>_6>|m`D%)lD<<~YQaU&$@<-J>lF_IAXf0i zTViw=XrPTama}ntmG8;gRdvv5O=GEpOs7OC<2)K|^`=HIiW=9whP(AnLmIsh5JAuG zs_ieOwbh)q@NBy{y_oTcsaMBN0lsWf2eUU27uOVa!gsuAr}zSrIWS8fzFS2A1Ug4d zGXxPCJ(2zT-H=jH2pjI_#s;lL$NyQ^R9kI)Mvo{%2$~`rfVbB)*+;3%TmLEwksU*q z;GgHo&a0n$3YrZZA(pgRDPciutWARC5Q zMI=NwC;IDAnJGxfOC{X%sF?`UuP0?aE3g2GHS`$7q0ERPD1_`+0X~WN637Dhd@i2F ztNr7j9~BRzOz4&jXttC~?^T0d**!#^3zXcM$=QM#rH9#PMNNp?ctBd4 zE^3)UTrbUPybSVP^x6qfulxG^ME>oh7sn4>n_}Zh;&BiW!g)?S?CY#{i8&akjB#I| zqgb8wqVTy0!7PGvmkJeLI7k~Juq=M)nP%BtyLlL}gmuYC7Bx+7){^lZt8`vy z3Y%8Em)U4$wZ~OA?>ihyA?YeVW0!-Mt_>{4E3rc<5uTR4QZj^Li-|V;1tjH79_e!L3|J7;>XO7WE&6HL`QR8>4>Gj-|Fuubm4TT zO5F54p70BDxA-q@ly{S%RQaCyjDgRdd3K%j+&*Z4_o%9VLl+dZa&}cnadWA5jc*D8 zsFkrhzaTH9!~!O5yb(_0JbVEyh=py*NFIj1pCK|a#BxXs=03cv0s=PoRT4nnFkwP& zF{^5q+oo%EfwdmmNW8|ysJ~+LTuaeJYi*> zd6ztc2rgUur!e~H_v5+Es1D^KFgIzg*h+M}=`oaAuI$kt9-3=aPuo*|?w|MlhrH7t z??Xe4a?v&hwE+{-WV)Ie)hasNBQ<-SWefDyw+4O23UDGahhKLFk^{(O`rNz-M(;0+ z0DFclgY@qWYWR$mdX;I^EZW|Qsc~D7K$ib`tE8P30EQ(p?*BGNt^vx>qyzvjK-Nq+ zvbezpg&`QD|1t&&L9C3vl5Y?93`8b+fov;$xU&V{nkyxcHD)auvFdvKd~75R8}#9! z`H5A`Ko?rFF?Y6=Yt+TN=qf|Vs^EI~Z!|mm?e$8da#0Ot(w1r#KKiZ2ZH;Ng-1fz1 z+yo^wmqe$W`)E8Ru!EPUM1c|i*FL3{?O(q@Ip&hFzse`T`KlgVG%ZmzwFARkaB8qn z8#NRp{_ZTf?h}4bu8*%9T(4?lbp1|3JYLA-qyHu6SW4@qC+`H{Lf8*4Z+_27*kD z#`|xrwZG^nO%6*O3fBgJ!@nFN)oKn)->OoZ9NE$;%+t+ffbyJoN1+hHv{@M8#J-T9sSrjK5J7{|OgWAIaLM@5g}xa*DwoqDgM0*e#=Y)aC8C!* zf)5ww#Z%2$T%D~oKM8{L;&s+qW5E@8J1;0DIX8HhHuJstYx2o$R2TcXl{Yjz$iX@> zF(glkL>~$h8cXeD{mU##AKVpXbS;Jz+e(=4GG(hfb+&8(5`#GwW*Vqua_^ zrJy1K4Me6*jl-+|pD#Q+@~6MvG7Mg|T1Kt5r~Z>y=S50_sO#^w`;2V`76eVaqb~hp zhJ|)elIh=X%j@+u(~+6f|Ldku)=i8BLdU){foQ8G=GH)TA@a07gM8zI(3w8m@A2l< z|M8*Tt1F3gq&2$X|erQ@A_Bpjfw))V?B zYY3BR%sA6n{(7F>Z?&@Fxt*~2iMm=w#|DTyi|5G`0$ExFS4qm*6X^i=jQ#{ zUsGb5f;P^Ba5G7m?#k5SF0V zkoX4gFm4awP{n#COHC5m$i75e?Iw06|6EILYCH(`h3L98(-E6A9KId>Ok-UW&`@&H zb+wr3YUQfgrsd_VTwe9z01YN{cvs8Nd=GK70^{=uT z22d=Ig2n!dx830NzmGS~`=u7Hq5}pajo6SH&Ve$3g&`2hyt{1ozF_-cY5sFovYs(w zN7*rr`S2CXsmUd2h>+VBlgH89M)&E`AQptna2VSIAKe~ujQ^iKc%7QMgPHeUVahSN z2#2qV+-efo&lsc1MDEv8OzygK!COwz*B)2pt{y=}OlRxSnGgjsTvFJO=$<`q_g}lw zCHV(czB45pLBsZ*RpqLtu#S5<@%c8%6(-U7&lp?n_zK(Ko>;lvUO-q&nHoO$1laQ? zF)|c-lG?e+=C5Mh=Y`6a|JsmyxRr0|4P3QADrsMz$~OLK{JJgVxqmwT&WqBG{|et3 zH&I$e8(ducYYk`q7zAgBp$j<~H8+berw7W*iN)Tj-=|wK-4Ww zUHYp(A^TJn4Tj$GsWaaYj*=+Hpl8=8QB!mjBi}b!hwsUx&4q7owGU9AdEoXwD`Oi^ zqXmN+svj&pdfWvR5NtmmA&Oo!ET3HR@0oc|bIqa^LxM?!98+Vj1np4QrBf37Eo z)yZ+!7ZI=F^H56}kC4N<ah zDC`JyykGW7TPQ86-P0+K6HeqS6iHgt=9#W-@R6_fSyXvODmjtU#|OaC`9% zH0k>VdX7))EP|Cx6mrzGe7bH%$(G<)M{Oh?c34wD0j)`NyJ}rKX$KSM+p^U`r^fRQ zpw|6E9z}>$F%f-P?JiBa%T9JCd}RE_>*oJlH*&H+K13DhJDQ8>CiZGNptiM+d3Yg3 zFZFHkOB!(on#=F^w^bxw$wuI{Q&6X)0N364jDUEs4FcmPLhLsaV1aTpUv`Xht1_X4x@_qZwP}L-H@Ov_)g-20y)puOE&Qwz zyX)eE=&O^gLO))~J2c zUSS|vrk#iMZdw;L-3yaTC_j_{P``u6IhU1{wO+e!f$Zp}3sjttn(b1}YfO~{$PBlE zV(g%;g=7X~UfjPp*;Tbana2nseVFBu+S*(l;UaKylEbo&+MDrye(Z-*s}vWAh0(cvJ;ANKu)Q?`+nEb2gTh(Txd5EJ zB^3Q2Hg+i;j3r zJ5IX;s><==-t&9h{L_pcsll(K`~&Ca&iBSF;?s{%W*~%&w78&yrS|?r^9758kv3e> zTI-u&zaw?vo+7a~V_@4{SYJnX43(w(fGw*{$h$NByO^CdlwY|u;E}~^omwDpI4}VA z+~~7Pgl$(NR%`{mKLpe{yCGzMFA|yHBgq3(|K5?#)&}UqLzn82IuOR0ISZk@7a0xe z%Fu<&dV0bGN_I;&o1os?W?_G~t8jH@t$qm};pUhUn73GnikJgI5!~U2pK%$M+qIt2 zbK=b!X2oeTo{#Z{r#Q7B#G$WDir0n$f;-!GMrDqnlID&d6P_Fbtl!!BwMSNgcGgpg zIE|t2a=xOZ|7^POQbCFlzr>cO6j@@mQijaiIR!G>Z`PS1U}#i#tKFZNAC%ZGukGe4 zjrO=%yqbN(5YPeAj8qQF68r@=6o&hud_CNvq%7?H}!uA#0=1eQeF!|~eAY6Qri zy|dSd2m1WmU}=uI=%ROSqjLO@ep_!#P7c20=EpM4LKcn=18LhqakDb=HY#r4VXTxw zZZ5h|kbuCY=#tkfaYl%I*b*Oo&Y+E(IrUS_>_cwL?Y(+alqk|xBKd)EeR#PO&^A9q zFK};kqCY?#4!Rd%Kh31}H#&=K#&7hFc;(`3RwRUyx(xe)kAu;`y2cf4EDrQm>v@nC zNTZVMdrQn`rEG6q8G)KIk{B#re8_y>Ob)5`^0l{s@ZlLnSwN#I@%AV@WClIhH9%6LSIvu zBeql%2;DA3i~Ohvm;^Vrxm@&OrNjIK=r^a#n-K(w^+45f$jrp6dU@;^nZ%#|O(7UL zW~YwS9C(i+{9cO`HeyU8!5f3s<3S@W zG~98Sr=qrR)DZ@n{&KrCF;qAXGF@jnZ70KUSXJEveN*LukIzKcN*g*SoA%cHUL!eV z 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 IM6N<$g8zR4dH?_b literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-user-defined.png b/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average-user-defined.png new file mode 100644 index 0000000000000000000000000000000000000000..6847cca39b2e2065ea353c404f500432cd486c11 GIT binary patch literal 48645 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 RzQ6*8)ReRp3vWMs{(qot;(q`D literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average.png b/Projects/Superalgos/PNGs/Docs/indicators/average-vs-average.png new file mode 100644 index 0000000000000000000000000000000000000000..598b9febe5a66a3f81e4328b2a002fca36b27f88 GIT binary patch literal 180000 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%0AO^ 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�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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/PNGs/Docs/indicators/chaikin-oscillator.png b/Projects/Superalgos/PNGs/Docs/indicators/chaikin-oscillator.png new file mode 100644 index 0000000000000000000000000000000000000000..b0698665e4224d9f36ef3cf941f77104ebdb48b8 GIT binary patch literal 65223 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 ffBYJ|wjVqXd?cSRC5jf2t Data Building Procedure -> Procedure Loop -> Procedure Javascript Code node." + }, + "paragraphs": [ + { + "style": "Title", + "text": "Indicator list:", + "updated": 1617873731007 + }, + { + "style": "List", + "text": "Chaikin Oscillator" + }, + { + "style": "Text", + "text": "The Chaikin Oscillator is the difference between the 3-day and 10-day EMAs of the Accumulation Distribution Line. Like other momentum indicators, this indicator is designed to anticipate directional changes in the Accumulation Distribution Line by measuring the momentum behind the movements." + }, + { + "style": "List", + "text": "ARPS Slow & ARPS Fast", + "updated": 1617875374428 + }, + { + "style": "Text", + "text": "ARPS - Average Range Percentage Spread measures the amount force of Bull Power and Bear Power. Two separate indicators measuring the same thing, in order to be used either separatly or combined.", + "updated": 1617957855552 + }, + { + "style": "List", + "text": "Average VS Average" + }, + { + "style": "Text", + "text": "The Average VS Average Oscillator can be used to recognize changes between a fast average and a slow average. Considering price movement, volume and a so called \"open interest\".", + "updated": 1617957863133 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json new file mode 100644 index 000000000..75afc7464 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json @@ -0,0 +1,73 @@ +{ + "topic": "Omega One Data Mine", + "pageNumber": "2", + "type": "Chaikin Oscillator", + "definition": { + "text": "The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n", + "updated": 1617876911680 + }, + "paragraphs": [ + { + "style": "Subtitle", + "text": "What is the Chaikin Oscillator?" + }, + { + "style": "Text", + "text": "The Chaikin oscillator is named for its creator Marc Chaikin. The oscillator measures the accumulation-distribution line of moving average convergence-divergence (MACD). To calculate the Chaikin oscillator, subtract a 10-day exponential moving average (EMA) of the accumulation-distribution line from a 3-day EMA of the accumulation-distribution line. This measures momentum predicted by oscillations around the accumulation-distribution line.", + "updated": 1617875532630 + }, + { + "style": "Callout", + "text": "A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish." + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/chaikin-oscillator.png" + }, + { + "style": "Subtitle", + "text": "How is the Chaikin Oscillator calculated?", + "updated": 1617875610441 + }, + { + "style": "List", + "text": "Calculate the Money Flow Multiplier (N)." + }, + { + "style": "List", + "text": "Multiply the Money Flow Multiplier (N) by volume to calculate Money Flow Volume (N)." + }, + { + "style": "List", + "text": "List a running total of N to draw the accumulation-distribution line (ADL)." + }, + { + "style": "List", + "text": "Compute the difference between 10 period and 3 period exponential moving averages to calculate the Chaikin oscillator." + }, + { + "style": "Subtitle", + "text": "Example of How to Use the Chaikin Oscillator" + }, + { + "style": "Text", + "text": "The purpose of the Chaikin oscillator is to identify underlying momentum during fluctuations in accumulation-distribution. Specifically, it applies the MACD indicator to accumulation-distribution rather than closing prices." + }, + { + "style": "Text", + "text": "For example, a trader wants to determine whether a stock price is more likely to go up or to fall and MACD is trending higher. The Chaikin oscillator generates a bullish divergence when it crosses above a baseline. The baseline is called the accumulation-distribution line. A cross above that line indicates that traders are accumulating, which is typically bullish." + }, + { + "style": "Text", + "text": "The Chaikin oscillator utilizes two primary buy and sell signals. First, a positive divergence is confirmed with a center-line crossover above the accumulation-distribution line. signaling a potential buying opportunity.. Second, a negative divergence is confirmed with a center-line crossover below the accumulation-distribution line., signaling a potential selling opportunity" + }, + { + "style": "Text", + "text": "A positive divergence signals a stock price is likely to rise, given the increase in accumulation. A negative divergence signals a stock price is likely to fall, given the increase in distribution." + }, + { + "style": "Subtitle", + "text": "" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json new file mode 100644 index 000000000..a68767c99 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json @@ -0,0 +1,131 @@ +{ + "topic": "Omega One Data Mine", + "pageNumber": "3", + "type": "ARPS Slow & ARPS Fast", + "definition": { + "text": "Measures the average Bull Power and average Bear Power in the average Total Range.", + "updated": 1617958264294 + }, + "paragraphs": [ + { + "style": "Note", + "text": "You can set different values for used periods at the top section of most indicators found in the Omega Data Mine -> Data Building Procedure -> Procedure Loop -> Procedure Javascript Code node.", + "updated": 1617957983880 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/arps-slow-arps-fast.png" + }, + { + "style": "Subtitle", + "text": "ARPS - Average Range Percentage Spread", + "updated": 1617957610783 + }, + { + "style": "Text", + "text": "ARPS Slow and ARPS Fast measures the Average Bull and Average Bear power within a given, configurable range." + }, + { + "style": "Text", + "text": "Two separate indicators that can be used either separatly or in combination with others." + }, + { + "style": "Text", + "text": "ARPS follows price action by using a SMA center line, and prints out the bullish power visualised by a blue line, and a red line for bearish power. The distance from the centerline represents the strength of the powers. The greater distance away from the center line, the greater advantage.", + "updated": 1617953949590 + }, + { + "style": "Text", + "text": "The distance between the bull and bear lines represents the average total range for the period." + }, + { + "style": "Text", + "text": "Looking at the Plotter Panel will give you the values measured in percentage (%)." + }, + { + "style": "Subtitle", + "text": "How is ARPS calculated?" + }, + { + "style": "Text", + "text": "All values are being calculated through a SMA function." + }, + { + "style": "List", + "text": "Bull Power is the measured distance between the candle low and candle close, divided the candle range.", + "updated": 1617952901003 + }, + { + "style": "List", + "text": "Bear Power is the measured distance between the candle high and candle close, divided the candle range.", + "updated": 1617952943789 + }, + { + "style": "List", + "text": "The average Bull Power and average Bear Power are divided through the Average Total Range for the same given period - Giving the Average Range Spread.", + "updated": 1617953325703 + }, + { + "style": "List", + "text": "All values are multiplied by 100 to convert it to precentage form (%)." + }, + { + "style": "Subtitle", + "text": "Change the input to optimise it for your use case!", + "updated": 1617953879921 + }, + { + "style": "Text", + "text": "Most of Omega indicators can use different period values. To change periods:", + "updated": 1617955135049 + }, + { + "style": "List", + "text": "Locate the Data Mine and expand it." + }, + { + "style": "List", + "text": "Expand the Indicator Bot node." + }, + { + "style": "List", + "text": "Find the Product Definition -> Data Building Procedure -> Procedure Loop -> Procedure Javascript Code." + }, + { + "style": "List", + "text": "Edit the Procedure Javascript Code node." + }, + { + "style": "List", + "text": "Put the text marker in the edit box, and press Arrow Up until you reach the top of the code." + }, + { + "style": "List", + "text": "Look for \"User defined values\".", + "updated": 1617954642138 + }, + { + "style": "List", + "text": "Enter the values of your choice." + }, + { + "style": "Note", + "text": "Remember that you have to delete existing data for the indicator in the Data-Storage folder, and re-start the Data Tasks needed for the indicator in the Network node before you can see any changes.", + "updated": 1617954918128 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/arps-code-node.png", + "updated": 1617954552809 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/arps-user-defined.png", + "updated": 1617954568478 + }, + { + "style": "Subtitle", + "text": "" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json new file mode 100644 index 000000000..1a7a36dff --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json @@ -0,0 +1,173 @@ +{ + "topic": "Omega One Data Mine", + "pageNumber": "4", + "type": "Average VS Average", + "definition": { + "text": "An oscillator that considers averages of price, volume and \"open interest\".", + "updated": 1617958214490 + }, + "paragraphs": [ + { + "style": "Note", + "text": "You can set different values for used periods at the top section of most indicators found in the Omega Data Mine -> Data Building Procedure -> Procedure Loop -> Procedure Javascript Code node.", + "updated": 1617958138349 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/average-vs-average.png" + }, + { + "style": "Subtitle", + "text": "Average VS Average" + }, + { + "style": "Text", + "text": "The Average VS Average Oscillator can be used to recognize changes between a fast average and a slow average. It measures Price Movement, Volume and a so called Open Interest.", + "updated": 1617958497266 + }, + { + "style": "Text", + "text": "The idea is to visualise if the trend weakens or gets stronger, within the current trend." + }, + { + "style": "Text", + "text": "The indicator is a zero-line cross indicator that is best used with an own rate and scale (in order to place it below the candle chart)." + }, + { + "style": "Text", + "text": "The elements in the indicator are:" + }, + { + "style": "List", + "text": "A zero-line that represents the slow average of the elements.", + "updated": 1617960380897 + }, + { + "style": "List", + "text": "A green line that shows fast average Bull Power compared to the slow average.", + "updated": 1617960429886 + }, + { + "style": "List", + "text": "A dotted line that shows the fast average Open Interest compared to the slow average.", + "updated": 1617960458863 + }, + { + "style": "List", + "text": "Faded green and red bars in the background that shows the fast average volume compared to the slow average volume. It changes colors depending on the previous value.", + "updated": 1617961835292 + }, + { + "style": "List", + "text": "Non-faded green and red bars close to the zero-line showing the fast price average compared to the slow price average. It changes colors depending on the previous value.", + "updated": 1617961849374 + }, + { + "style": "Subtitle", + "text": "What is \"Open Interest\"?" + }, + { + "style": "Text", + "text": "The idea of measuring Open Interest - is that a red candle might not be an indication of a bearish interest and vice versa. Considering volume, candle direction and amount movement defines the strength of Open Interest.", + "updated": 1617961616124 + }, + { + "style": "List", + "text": "Bull Candle and Volume Increase = Bull Interest" + }, + { + "style": "List", + "text": "Bull Candle and Volume Decrease = Bear Interest" + }, + { + "style": "List", + "text": "Bear Candle and Volume Increase = Bear Interest" + }, + { + "style": "List", + "text": "Bear Candle and Volume Decrease = Bull Interest" + }, + { + "style": "Subtitle", + "text": "How is the Average VS Average calculated?" + }, + { + "style": "List", + "text": "Bull Power is defined by measuring the value between candle min and candle close, out of the total candle range. Comparing the fast average Bull Power through the slow average Bull Power.", + "updated": 1617961207015 + }, + { + "style": "List", + "text": "Volume is measured by the fast average Total Volume through the slow average Total Volume.", + "updated": 1617961227511 + }, + { + "style": "List", + "text": "The fast average Price is compared to the slow average Price.", + "updated": 1617961304593 + }, + { + "style": "List", + "text": "The fast average Open Interest is compared to the slow average Open Interest. ", + "updated": 1617961386984 + }, + { + "style": "Subtitle", + "text": "Change the input to optimise it for your use case!", + "updated": 1617953879921 + }, + { + "style": "Text", + "text": "Most of Omega indicators can use different period values. To change periods:", + "updated": 1617955135049 + }, + { + "style": "List", + "text": "Locate the Data Mine and expand it." + }, + { + "style": "List", + "text": "Expand the Indicator Bot node." + }, + { + "style": "List", + "text": "Find the Product Definition -> Data Building Procedure -> Procedure Loop -> Procedure Javascript Code." + }, + { + "style": "List", + "text": "Edit the Procedure Javascript Code node." + }, + { + "style": "List", + "text": "Put the text marker in the edit box, and press Arrow Up until you reach the top of the code." + }, + { + "style": "List", + "text": "Look for \"User defined values\".", + "updated": 1617954642138 + }, + { + "style": "List", + "text": "Enter the values of your choice." + }, + { + "style": "Note", + "text": "Remember that you have to delete existing data for the indicator in the Data-Storage folder, and re-start the Data Tasks needed for the indicator in the Network node before you can see any changes.", + "updated": 1617954918128 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/average-vs-average-code-node.png", + "updated": 1617958956443 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/indicators/average-vs-average-user-defined.png", + "updated": 1617958965558 + }, + { + "style": "Text", + "text": "" + } + ] +} \ No newline at end of file From 17afa41ccb370ea7dcf727c0460bc982056aac1c Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 9 Apr 2021 14:09:44 +0200 Subject: [PATCH 14/32] Bug FIX: Coninbase Pro handling of cancelled orders --- .../Trading-Bot/Low-Frequency-Trading/TradingOrders.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js index 380a27253..c3b50a007 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOrders.js @@ -643,7 +643,7 @@ exports.newSuperalgosBotModulesTradingOrders = function (processIndex) { let message let docs - + if (order === undefined) { message = 'Order Status Not Sync With Exchange' @@ -714,7 +714,7 @@ exports.newSuperalgosBotModulesTradingOrders = function (processIndex) { TS.projects.superalgos.utilities.docsFunctions.buildPlaceholder(docs, undefined, undefined, undefined, undefined, undefined, contextInfo) tradingSystem.addInfo([tradingSystemOrder.id, message, docs]) - return + return true } const AT_EXCHANGE_STATUS = { From e07253124cf15fd1b1c7c2a5b2159c241367afb2 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:09:45 +0200 Subject: [PATCH 15/32] Change name of Omega to Omega One --- Projects/Superalgos/Plugins/Data-Mines/Omega One.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Projects/Superalgos/Plugins/Data-Mines/Omega One.json diff --git a/Projects/Superalgos/Plugins/Data-Mines/Omega One.json b/Projects/Superalgos/Plugins/Data-Mines/Omega One.json new file mode 100644 index 000000000..c9f447b78 --- /dev/null +++ b/Projects/Superalgos/Plugins/Data-Mines/Omega One.json @@ -0,0 +1 @@ +{"type":"Data Mine","name":"Omega One","config":"{\n \"codeName\": \"Omega-One\"\n}","project":"Superalgos","sensorBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Chaikin Oscillator","project":"Superalgos","id":"130f1639-b299-4ca8-96eb-25c8345e09e4","savedPayload":{"position":{"x":13957.729481237811,"y":17901.141979655422},"targetPosition":{"x":14015.96376638588,"y":18118.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"5b0389ae-3da9-4628-bc20-1041faef76be"}}}],"outputDatasetFolders":[],"id":"e54488da-6999-437b-8a2d-85709728bb02","savedPayload":{"position":{"x":14015.96376638588,"y":18118.475290570463},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"1ff01e67-048e-4d80-a944-b1b86f21f42b","savedPayload":{"position":{"x":14143.886491396086,"y":17681.058769490315},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"c4fcc40a-427d-4c69-90a9-76abdc87b857","savedPayload":{"position":{"x":14214.185526065303,"y":17677.374553197562},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"2cb0d0f1-a9dc-4791-9952-0878eeaa96bd","savedPayload":{"position":{"x":14282.182366522136,"y":17695.594251685838},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"6e898c07-cb2e-4589-bd33-9b3c6b585bae","savedPayload":{"position":{"x":14341.221008260825,"y":17733.93439392301},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"2ea98444-5707-42c3-a6d0-0c4d7cceec15","savedPayload":{"position":{"x":14190.666621830082,"y":17901.141979655422},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74","savedPayload":{"position":{"x":14392.396103067893,"y":18017.610549951558},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"4a247a06-dfc4-400b-a3b8-fa9d57847f6a","savedPayload":{"position":{"x":14291.531362448988,"y":18277.574316337435},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"9d6d825e-c8cf-4d42-828c-62a1ba12bd32","savedPayload":{"position":{"x":14291.531362448988,"y":18394.04288663357},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e51bc1f1-1063-4d69-9699-3952ad33a056","savedPayload":{"position":{"x":14074.198051533947,"y":18335.808601485503},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Chaikin Oscillator","project":"Superalgos","id":"3d8886e0-c7a2-43aa-91c4-7698757a50e8","savedPayload":{"position":{"x":14656.000000000002,"y":17874.58378961345},"targetPosition":{"x":14431.000000000002,"y":18264.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108"}}}],"outputDatasetFolders":[],"id":"7ed09a77-8e5a-4f61-a182-ed93aa9e8037","savedPayload":{"position":{"x":14431.000000000002,"y":18264.29522131645},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Daily","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"61339b0d-ee5d-4848-a59c-b3f6d5ecfc07","savedPayload":{"position":{"x":14820.711431703,"y":18039.29522131645},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"21243e1a-a52f-40f7-9087-483a49a574a8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"b0e714a3-f496-407a-b1e5-b722df1b8e96","savedPayload":{"position":{"x":14913.909483236945,"y":18110.808601485503},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{\n \"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"7ddfb356-e8b3-4e49-9642-670f81d29b29","savedPayload":{"position":{"x":14985.422863405996,"y":18204.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"3ed165f6-6c65-445f-b70a-70275435ffca","savedPayload":{"position":{"x":15030.37805353308,"y":18312.538082723313},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"d9dc3be3-7565-4801-9d18-2b25380dcf87","savedPayload":{"position":{"x":15045.711431703,"y":18429.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"50b4b77b-7aae-4fb8-b147-4e77438e3278","savedPayload":{"position":{"x":14595.711431703,"y":18429.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"21243e1a-a52f-40f7-9087-483a49a574a8","savedPayload":{"position":{"x":14656.000000000002,"y":18654.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"124bcc91-61a1-40a1-a0b8-08179b8c16f6","savedPayload":{"position":{"x":14400.855715851501,"y":18766.50665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"ffa4c8b2-81bc-4f09-a54b-7fc71543b8f5","savedPayload":{"position":{"x":14318.500000000002,"y":18848.86236887095},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9c9a84d7-7bcf-4ffa-96db-a4a0b51d8e93","savedPayload":{"position":{"x":14206.000000000002,"y":18654.00665301945},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"singularVariableName\": \"chaikinOscillator\",\n \"pluralVariableName\": \"chaikinOscillators\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"5b0389ae-3da9-4628-bc20-1041faef76be","savedPayload":{"position":{"x":14264.438536534506,"y":18819.208347863343},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108","savedPayload":{"position":{"x":14235.433991612475,"y":19002.335837297276},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"3b204f99-f7d6-4d97-96f5-9e0f6cbc0558","savedPayload":{"position":{"x":14833.139338556775,"y":19494.60328091257},"targetPosition":{"x":14536.832836378235,"y":19447.672941400502},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cc3721e3-1409-4d80-8b1d-2d76ee03aefa","savedPayload":{"position":{"x":14536.832836378235,"y":19447.672941400502},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"a7081fb9-9143-463f-8e64-270dda8190dc","savedPayload":{"position":{"x":14664.790402911622,"y":19825.00667060036},"targetPosition":{"x":14452.658368555658,"y":19612.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"128aca84-d3ff-45ec-a8d2-b1fd4e942274","savedPayload":{"position":{"x":14452.658368555658,"y":19612.874636244396},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if ( isNaN(variable.chaikinOscillator ) )\n{ variable.chaikinOscillator = 0 }\nelse\n{ variable.chaikinOscillator }","project":"Superalgos","id":"eefbdfb1-b1b7-46c9-b283-f6de0dd556d1","savedPayload":{"position":{"x":14310.921843467799,"y":19845.202355156245},"targetPosition":{"x":14287.456673711764,"y":19697.049104066973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7f4e57b6-1d97-4902-8c5b-04d0ddaac1e6","savedPayload":{"position":{"x":14287.456673711764,"y":19697.049104066973},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Zero Line","config":"{\n \"codeName\": \"zeroLine\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"0","project":"Superalgos","id":"45c55257-fc58-4b76-9310-6471ff58182a","savedPayload":{"position":{"x":14036.230609316899,"y":19801.695537773197},"targetPosition":{"x":14104.32918427783,"y":19668.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3a6a9b74-37a9-48c4-956c-a6d6a5ae0080","savedPayload":{"position":{"x":14104.32918427783,"y":19668.044559144942},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"28f4f675-6764-4e30-b797-0ea44a6dfa53","savedPayload":{"position":{"x":14240.526334199694,"y":19400.742601888433},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Loop Code */\n\n/* Chaikin Oscillator\n\nKEY TAKEAWAYS\n- The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n- A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish.\n\n1. Money Flow Multiplier = [(Close - Low) - (High - Close)] / (High - Low) \n2. Money Flow Volume = Money Flow Multiplier x Volume for the Period\n3. ADL = Previous ADL + Current Period's Money Flow Volume\n4. Chaikin Oscillator = ('fast'-period EMA of ADL) - ('slow'-period EMA of ADL) */\n\n\nlet fastPeriod = 5 // Change value to set 'fast' period (must be less than or equal to 'fast')\nlet slowPeriod = 17 // Change value to set 'slow' period (must be greater than or equal to 'slow')\n\nlet candle = record.current\nlet volume = getElement('volumes', candle)\n\n\n// Set varibles\nvariable.totalVolume = volume.buy + volume.sell\t\nvariable.moneyFlowMultiplier = ((candle.close - candle.min) - (candle.max - candle.close)) / (candle.max - candle.min) \nvariable.moneyFlowVolume = variable.moneyFlowMultiplier * variable.totalVolume \nvariable.currentADL = variable.totalVolume + variable.moneyFlowVolume\nvariable.savedADL.push(variable.currentADL) // Push the currentADL into an array to be able to use \"previous ADL\"\n\nif (variable.savedADL.length > 2) { // Make sure we only save the current and previous\n variable.savedADL.splice(0, 1)\n}\n\n// Calculating the 'accDistLine' using previous ADL value if it is defined, else current\nif (variable.savedADL[0] === 'undefined')\n{variable.accDistLine = variable.savedADL[1] + variable.moneyFlowVolume} // Calculating with Current ADL\nelse\n{variable.accDistLine = variable.savedADL[0] + variable.moneyFlowVolume} // Calculating with Previous ADL\n\n\n// Calculate fastEMA and slowEMA of ADL\nif(isNaN(variable.previousEmaFast))\n{variable.previousEmaFast = variable.accDistLine}\nelse\n{variable.previousEmaFast}\n\nvariable.fastEMA = calculateEMAs(fastPeriod, variable.accDistLine, variable.previousEmaFast)\nvariable.previousEmaFast = variable.fastEMA\n\nif(isNaN(variable.previousEmaSlow))\n{variable.previousEmaSlow = variable.accDistLine}\nelse\n{variable.previousEmaSlow}\nvariable.slowEMA = calculateEMAs(slowPeriod, variable.accDistLine, variable.previousEmaSlow)\nvariable.previousEmaSlow = variable.slowEMA\n\n\n// Create EMA function for 'fast' and 'slow' ADL\nfunction calculateEMAs(periods, adl, previousEMA) {\n let k = 2 / (periods + 1)\n return adl * k + previousEMA * (1-k)\n}\n\n// Calculate Chaikin Oscillator value\nvariable.chaikinOscillator = variable.fastEMA - variable.slowEMA\n\n// Happy trading! CJ.","project":"Superalgos","id":"43f087d9-6da9-4387-a3ee-7e7e4ca247b3","savedPayload":{"position":{"x":13947.33381066081,"y":19411.075663396023},"targetPosition":{"x":13936.880964334045,"y":19311.623473859196},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2c6eff8c-0beb-4068-a9c6-26a06cbd242d","savedPayload":{"position":{"x":13936.880964334045,"y":19311.623473859196},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build arrays \n\nvariable.savedADL = []\n\n","project":"Superalgos","id":"67b6e8ff-b104-47c1-b8ec-a8847bce6b7a","savedPayload":{"position":{"x":13819.517534074947,"y":19390.831553964606},"targetPosition":{"x":13860.191198382527,"y":19299.477008200345},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c6684774-9a86-4b1b-a1ef-5ddd2027ae00","savedPayload":{"position":{"x":13860.191198382527,"y":19299.477008200345},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ba9d9a5f-61eb-49d8-a73d-15ca3e00ecd7","savedPayload":{"position":{"x":13921.201694843896,"y":19162.445189553953},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"31fee6c0-b932-4604-8a47-aa31fd679291","savedPayload":{"position":{"x":13968.132034355966,"y":18866.138687375413},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Chaikin Oscillator","id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae"}}}],"id":"f7bdd106-bdc2-4a99-8bce-173e94322727","savedPayload":{"position":{"x":13756.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Slow","project":"Superalgos","id":"4a233d99-e570-4936-a3f4-613c75213bc8","savedPayload":{"position":{"x":15567.729481237811,"y":17623.641979655422},"targetPosition":{"x":15625.963766385876,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c"}}}],"outputDatasetFolders":[],"id":"03c83aa5-5473-499d-8990-b99aa25cd543","savedPayload":{"position":{"x":15625.963766385876,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"af2be1a5-6589-49d4-8f89-8ae1cb3162f8","savedPayload":{"position":{"x":15686.182336682012,"y":17743.54743264471},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"ce465417-0658-430a-9888-2ffefee15357"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"24d1f7a4-66af-4169-a118-93618334f6ae","savedPayload":{"position":{"x":15771.549479256044,"y":17732.308635112942},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c541371a-27a9-436c-9342-081d67231318","savedPayload":{"position":{"x":15839.860194607763,"y":17784.725290570463},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"6f23340b-8d1f-4652-876f-4a70c3e21aec","savedPayload":{"position":{"x":15742.432336682012,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"ce465417-0658-430a-9888-2ffefee15357","savedPayload":{"position":{"x":16002.396103067893,"y":17740.110549951558},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"2597670e-3304-4839-ad6d-826290e3eabc","savedPayload":{"position":{"x":15901.531362448988,"y":18000.07431633744},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"96c24e28-6cd5-4d1f-9a35-35997b7e160a","savedPayload":{"position":{"x":15901.531362448988,"y":18116.542886633568},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0f2f6a8-0241-4aba-8751-a632e066d047","savedPayload":{"position":{"x":14118.132034355966,"y":18866.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Slow","project":"Superalgos","id":"1aedf3a0-5890-424e-a1f2-e54fc52659e1","savedPayload":{"position":{"x":16266.000000000002,"y":17597.08378961345},"targetPosition":{"x":16041.000000000002,"y":17986.79522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424"}}}],"outputDatasetFolders":[],"id":"d0cc5e79-a820-47d7-ad12-406b09b6f4dd","savedPayload":{"position":{"x":16041.000000000002,"y":17986.79522131645},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"fd87cb30-87eb-4ba7-9763-da651e48813c","savedPayload":{"position":{"x":16450.79899745976,"y":17774.10489744401},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3d36499e-ce24-4f0d-9875-48f7b63d05c8","savedPayload":{"position":{"x":16555.42711435863,"y":17868.31247704702},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"77a7753f-af11-40ac-a65d-ca75123b04ea","savedPayload":{"position":{"x":16625.822623626736,"y":17990.24107572407},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"6efb002f-6126-42ca-93fe-21c67f833c60","savedPayload":{"position":{"x":16655.094722342554,"y":18127.955472710124},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"b0367e88-7e82-42cd-944d-c4e9ca80d945","savedPayload":{"position":{"x":16205.711431703001,"y":18151.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08","savedPayload":{"position":{"x":16266.000000000002,"y":18376.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0b78bc25-8a2b-4a22-bcda-635f3b9b1187","savedPayload":{"position":{"x":16010.855715851498,"y":18489.00665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"4eec532d-30b6-4356-b69d-2460739799ce","savedPayload":{"position":{"x":15928.500000000002,"y":18571.362368870945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"160e01a5-da62-4b67-9042-68751949ee96","savedPayload":{"position":{"x":13986.330085889911,"y":19184.33673890936},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"singularVariableName\": \"slowARPS\",\n \"pluralVariableName\": \"slowARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c","savedPayload":{"position":{"x":13910.83713266845,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424","savedPayload":{"position":{"x":13760.83713266845,"y":19451.455642263958},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"9b3ec784-f875-4a31-9f2d-fdba3a4dd237","savedPayload":{"position":{"x":13968.132034355966,"y":20089.44374852799},"targetPosition":{"x":13725.426936043481,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"04be52be-03fa-4548-8ac1-11a688786301","savedPayload":{"position":{"x":13725.426936043481,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"be9d5502-b6ea-4109-931c-263e4ef39166","savedPayload":{"position":{"x":13835.392989106482,"y":20222.18279377747},"targetPosition":{"x":13659.057413418739,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d7f463c1-7208-4b96-8d46-893ee111e6f7","savedPayload":{"position":{"x":13659.057413418739,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"74a4a7e5-b4d5-46bd-9a3e-92c2705646cf","savedPayload":{"position":{"x":13621.779485199722,"y":20164.748029485323},"targetPosition":{"x":13575.426936043481,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3fe424b8-a927-4a4b-b82a-9fe013546966","savedPayload":{"position":{"x":13575.426936043481,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"735b28dc-532e-471f-bcdd-84ea80114a0e","savedPayload":{"position":{"x":13482.721837730996,"y":20186.772597152503},"targetPosition":{"x":13482.721837730996,"y":20036.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"86568b58-7899-4b50-80cd-4223c5b2a528","savedPayload":{"position":{"x":13482.721837730996,"y":20036.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"bf2645de-583b-4051-9f17-38935cb7d421","savedPayload":{"position":{"x":13343.66419026227,"y":20164.748029485323},"targetPosition":{"x":13390.016739418512,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e799bf00-cf17-4adb-92e9-d5c66bce7261","savedPayload":{"position":{"x":13390.016739418512,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"7c4af3a5-a3d3-4569-9074-6e5605f53cc2","savedPayload":{"position":{"x":13218.218474199382,"y":20100.83024462123},"targetPosition":{"x":13306.386262043254,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5d00b15c-7803-4044-8b44-166ea605e241","savedPayload":{"position":{"x":13306.386262043254,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"cde2b51c-7d16-4ee6-8b35-1dad3e18227f","savedPayload":{"position":{"x":13118.66419026227,"y":20001.275960684117},"targetPosition":{"x":13240.016739418512,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"af19875c-861c-407e-9275-8fb2111277dc","savedPayload":{"position":{"x":13240.016739418512,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"da247784-c47c-41ae-b764-519d47700a50","savedPayload":{"position":{"x":13054.746405398178,"y":19875.83024462123},"targetPosition":{"x":13197.404882842451,"y":19829.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"56774359-2338-4b22-bf66-26835a7f1266","savedPayload":{"position":{"x":13197.404882842451,"y":19829.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"79052dd4-e79c-4139-b034-a2b59a7cad5f","savedPayload":{"position":{"x":13032.721837730996,"y":19736.772597152503},"targetPosition":{"x":13182.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"30c88625-0df0-4647-9ebf-51a5ef868f58","savedPayload":{"position":{"x":13182.721837730996,"y":19736.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8b9a90a7-170a-4f59-8132-bd890aab9a26","savedPayload":{"position":{"x":13482.721837730996,"y":19736.772597152503},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 17 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ. :-)","project":"Superalgos","id":"adea7d76-a792-4556-b017-093de9fe2b0f","savedPayload":{"position":{"x":13268.09683828102,"y":19536.760753427396},"targetPosition":{"x":13331.028877386005,"y":19459.0461572817},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a6150e04-c314-489d-824f-23afa0072a7e","savedPayload":{"position":{"x":13331.028877386005,"y":19459.0461572817},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"cc836ccb-c2dc-4ba5-9fcd-080a69c50b8a","savedPayload":{"position":{"x":13192.03182941918,"y":19432.066250449483},"targetPosition":{"x":13285.389872068901,"y":19396.22945549495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"679b4d08-204b-4564-9324-19f7ed005c08","savedPayload":{"position":{"x":13285.389872068901,"y":19396.22945549495},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ab30d1a8-1659-46d7-9620-b2783b58feef","savedPayload":{"position":{"x":13425.426936043481,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e34788bb-3c57-4a14-abb5-451f35533e49","savedPayload":{"position":{"x":13668.132034355966,"y":19166.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Slow","id":"e12e90bd-bc37-42da-9f83-7b1506391bd9"}}}],"id":"81becef8-2376-47a7-8cdf-a559c45ed950","savedPayload":{"position":{"x":13668.132034355966,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Fast","project":"Superalgos","id":"a4be096d-4fa4-44ba-983d-af202af96d7d","savedPayload":{"position":{"x":16144.729481237811,"y":17296.141979655422},"targetPosition":{"x":16202.96376638588,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"08336286-f6f1-4fa5-ba1e-912897063979"}}}],"outputDatasetFolders":[],"id":"0727df65-0f8c-4415-a85f-d9e322240273","savedPayload":{"position":{"x":16202.96376638588,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"5790535f-17f2-4ee0-bded-368ebd9489dc","savedPayload":{"position":{"x":16263.182336682012,"y":17416.04743264471},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"ee739a5f-2a9e-40d4-a557-8cb53521d7e3","savedPayload":{"position":{"x":16348.549479256048,"y":17404.808635112942},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c926b53f-07cb-4d2c-8260-9dadc6bb2f1b","savedPayload":{"position":{"x":16416.86019460776,"y":17457.225290570463},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"73f3249b-2f51-4399-950d-186d6d68c78e","savedPayload":{"position":{"x":16319.432336682012,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1","savedPayload":{"position":{"x":16579.39610306789,"y":17412.610549951558},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"9261d5a5-4da2-4119-a78a-7d231491c2ee","savedPayload":{"position":{"x":16478.531362448986,"y":17672.57431633744},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"68b54ef4-857f-4a75-88ea-319ba92f5fd9","savedPayload":{"position":{"x":16478.531362448986,"y":17789.042886633568},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b138ab56-8d61-44f0-b0e9-27f171bbbfbe","savedPayload":{"position":{"x":13774.198051533947,"y":19272.204704553395},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Fast","project":"Superalgos","id":"f679b2a9-f5ce-46fb-852e-be58c502a0da","savedPayload":{"position":{"x":16843,"y":17269.58378961345},"targetPosition":{"x":16618,"y":17659.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9"}}}],"outputDatasetFolders":[],"id":"d4701ed1-5658-45b5-8835-14f1414491f3","savedPayload":{"position":{"x":16618,"y":17659.29522131645},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"258d211e-d162-4064-ab04-a6f36ae306e6","savedPayload":{"position":{"x":17027.79899745976,"y":17446.60489744401},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"82262685-1d6f-4c35-8584-3f13ad1b0921","savedPayload":{"position":{"x":17132.427114358637,"y":17540.81247704702},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"c7c3c7a8-4fb5-45f2-bb11-51d6cfdfda3e","savedPayload":{"position":{"x":17202.822623626736,"y":17662.74107572407},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"0f0a43f4-60d2-42fa-93fa-be2e21f8c302","savedPayload":{"position":{"x":17232.094722342554,"y":17800.455472710124},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"d29fbaa9-5eb9-4cb0-94e3-3ea6d18f20c2","savedPayload":{"position":{"x":16782.711431703,"y":17824.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf","savedPayload":{"position":{"x":16843,"y":18049.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0394d6ce-4648-4295-aa21-431adf475fe3","savedPayload":{"position":{"x":16587.855715851503,"y":18161.50665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"c90561ab-2b37-4df4-8f06-10e06ed4edee","savedPayload":{"position":{"x":16505.5,"y":18243.862368870945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"8634ce99-462c-4cf4-b55a-e939bd458a6b","savedPayload":{"position":{"x":13456.000000000002,"y":19404.00665301945},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Fast","config":"{\n \"codeName\": \"fastARPS\",\n \"singularVariableName\": \"fastARPS\",\n \"pluralVariableName\": \"fastARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"08336286-f6f1-4fa5-ba1e-912897063979","savedPayload":{"position":{"x":13290.798305156108,"y":19462.445189553953},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9","savedPayload":{"position":{"x":13107.670815722175,"y":19433.440644631923},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"aa7ec15b-6515-41b2-bcf8-caf282254a2f","savedPayload":{"position":{"x":17020.13933855677,"y":18701.881922864293},"targetPosition":{"x":16723.832836378235,"y":18748.81226237636},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0bdacd74-1544-46ef-80b8-c36764f748f1","savedPayload":{"position":{"x":16723.832836378235,"y":18748.81226237636},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"6ba23d0d-4820-44d9-882e-12b53e3340c5","savedPayload":{"position":{"x":17020.13933855677,"y":18889.60328091257},"targetPosition":{"x":16723.832836378235,"y":18842.672941400506},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0fd74c82-d165-42ba-a60e-2557ef8f7469","savedPayload":{"position":{"x":16723.832836378235,"y":18842.672941400506},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"3548eb27-ca3d-4b56-851d-815322a07af3","savedPayload":{"position":{"x":16828.479270084455,"y":19000.038326771228},"targetPosition":{"x":16694.8282914562,"y":18931.939751810296},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"70fe36c1-0c68-49e7-a2fa-8f60232ff4ef","savedPayload":{"position":{"x":16694.8282914562,"y":18931.939751810296},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"1473d657-276b-406b-90e6-a66131604ff6","savedPayload":{"position":{"x":16745.724385733636,"y":19113.940653422378},"targetPosition":{"x":16639.658368555654,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"571474ac-c4ed-4ee7-af2c-e4a56098cfad","savedPayload":{"position":{"x":16639.658368555654,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"0b9787b0-9547-4688-be4a-48a727f42e04","savedPayload":{"position":{"x":16631.822059082486,"y":19196.695537773197},"targetPosition":{"x":16563.723484121554,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e255bc82-518f-41e0-b9c5-dc573217cfb9","savedPayload":{"position":{"x":16563.723484121554,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"8e31b59b-6550-469d-a818-edb4b9eda503","savedPayload":{"position":{"x":16497.921843467797,"y":19240.20235515624},"targetPosition":{"x":16474.456673711764,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"4c52fc87-fac3-4a74-928c-beff9640f538","savedPayload":{"position":{"x":16474.456673711764,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"47dd70e8-0226-4bda-835d-8b426fc2e23d","savedPayload":{"position":{"x":16357.13082493159,"y":19240.20235515624},"targetPosition":{"x":16380.595994687626,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ce61113d-7b92-454d-9d22-557fb0532385","savedPayload":{"position":{"x":16380.595994687626,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"c456e845-561a-4761-b7d8-0424bdd76729","savedPayload":{"position":{"x":16223.230609316897,"y":19196.695537773197},"targetPosition":{"x":16291.329184277829,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b2f7070c-8430-4a3b-9477-b71fa1215cdb","savedPayload":{"position":{"x":16291.329184277829,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"231fd372-de75-42b8-827b-7a315ac96a7f","savedPayload":{"position":{"x":16109.328282665747,"y":19113.940653422378},"targetPosition":{"x":16215.394299843729,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ba0880ca-226d-4e4c-a2d6-620d6dc5cfe0","savedPayload":{"position":{"x":16215.394299843729,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"867c1562-64d7-47d1-ab5b-6de88bc115dd","savedPayload":{"position":{"x":12709.264051131018,"y":19438.53298721914},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 3 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ! :-)","project":"Superalgos","id":"35a38ab1-ff66-4072-b82f-6cc2f56ff6f4","savedPayload":{"position":{"x":12698.93098962343,"y":19145.34046368026},"targetPosition":{"x":12798.383179160257,"y":19134.88761735349},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"77b480da-70d7-43ab-bd51-98044b9350be","savedPayload":{"position":{"x":12798.383179160257,"y":19134.88761735349},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"8b82130d-b51f-410c-82b3-34abb02bc3a4","savedPayload":{"position":{"x":12719.175099054848,"y":19017.524187094394},"targetPosition":{"x":12810.529644819107,"y":19058.197851401972},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e1fcfd73-c477-4574-986f-85583fa489af","savedPayload":{"position":{"x":12810.529644819107,"y":19058.197851401972},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"19eacb84-6904-4b79-aa5c-7f6c69c89b04","savedPayload":{"position":{"x":12947.561463465498,"y":19119.208347863343},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b099e79b-ee47-4937-bf88-43f1a4f55a8c","savedPayload":{"position":{"x":13243.867965644038,"y":19166.138687375413},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Fast","id":"fdffbdff-a42f-47db-b068-4a711070bef3"}}}],"id":"b1eaf829-987d-4ddc-92c7-10edb3e0d194","savedPayload":{"position":{"x":13456.000000000002,"y":18954.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Average VS Average","project":"Superalgos","id":"2edf9e6c-e713-45fc-9764-73f1465f1352","savedPayload":{"position":{"x":13298.615075075051,"y":18964.99615794743},"targetPosition":{"x":13123.757233747232,"y":18823.399069961215},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15"}}}],"outputDatasetFolders":[],"id":"322cf5e8-7f9d-4bdd-abed-5f78672b93a9","savedPayload":{"position":{"x":13123.757233747232,"y":18823.399069961215},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"87830a28-1634-48f8-a226-506c89ade476","savedPayload":{"position":{"x":13138.198836524625,"y":18920.974720510905},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3ab9def4-53a1-458f-83d7-b3be09887d4e","savedPayload":{"position":{"x":13100.330725060212,"y":18979.28649860078},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"78ca9971-aa46-458f-b8d9-354426317bd4","savedPayload":{"position":{"x":13035.419976144436,"y":19004.20340059676},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"f51ac085-64ae-45c2-9467-e98eb801379d","savedPayload":{"position":{"x":12968.260289627915,"y":18986.208016830733},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"85b582f1-7cc2-4535-ac54-7df234e3db4f","savedPayload":{"position":{"x":13029.532181067105,"y":18891.857577936873},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8","savedPayload":{"position":{"x":12878.503883151308,"y":19126.26173524281},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"885a6862-324a-4528-b842-8c40f0aafc97","savedPayload":{"position":{"x":12807.3023044332,"y":18856.659823302816},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"bf186655-c6bd-487d-ab02-65b7535b80b1","savedPayload":{"position":{"x":12738.843796457542,"y":18762.434770622694},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f8c12a67-d98f-4a20-9f95-5e590321403f","savedPayload":{"position":{"x":13243.867965644038,"y":19316.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Average VS Average","project":"Superalgos","id":"3d362705-7d3b-4205-af78-6aeeccd326b9","savedPayload":{"position":{"x":12749.31287115968,"y":19396.915298070246},"targetPosition":{"x":12702.275062689236,"y":18949.380445154526},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c"}}}],"outputDatasetFolders":[],"id":"41ea773f-0b13-4691-8393-f562352f89ee","savedPayload":{"position":{"x":12702.275062689236,"y":18949.380445154526},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"627ead20-a71e-47c1-8d5d-42506ab2433d","savedPayload":{"position":{"x":12519.243573305126,"y":19360.475901093694},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"de6cab83-afd5-4f5a-ad2e-1cf0fc07b7e8","savedPayload":{"position":{"x":12401.810255566577,"y":19357.400801445783},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"f0dea610-c1c0-4f2f-9d79-8e2cfc90b582","savedPayload":{"position":{"x":12289.174275450572,"y":19324.036504117143},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"f54e9145-daed-48a1-a2bb-ce82ceec4b78","savedPayload":{"position":{"x":12189.011588862255,"y":19262.656730833613},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"947c751a-393b-4499-88d0-54d112a2d923","savedPayload":{"position":{"x":12108.148117365956,"y":19177.444411709588},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"03d0b6f4-795f-43f9-aed7-398ff9be2c31","savedPayload":{"position":{"x":12472.205764834682,"y":18912.941048177974},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec","savedPayload":{"position":{"x":12291.179606750065,"y":18766.34895577042},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"b7661232-5ecd-42e5-b4e2-0387253c51cc","savedPayload":{"position":{"x":12431.46982776093,"y":18525.364496474027},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"25b50fcf-ad3c-436c-90b4-9b83dfafd4fb","savedPayload":{"position":{"x":12449.689526249205,"y":18410.32984754675},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"90fe53a1-9c47-4b05-af43-8876c468d379","savedPayload":{"position":{"x":12925.669914110093,"y":19184.33673890936},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"singularVariableName\": \"averageVsAverage\",\n \"pluralVariableName\": \"averageVsAverages\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15","savedPayload":{"position":{"x":12767.532389956295,"y":19108.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c","savedPayload":{"position":{"x":12658.551010755493,"y":18958.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"abf7c3f9-418d-44be-9d5f-68117e6e26cf","savedPayload":{"position":{"x":11465.997291705151,"y":19436.727492435068},"targetPosition":{"x":11890.26136041708,"y":19012.46342372314},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"fc0364a2-a5b0-4f77-81cb-448f3a532efb","savedPayload":{"position":{"x":11958.596466474826,"y":19114.405409046878},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"615b00d5-f0e5-48e4-883f-8985b00b7470","savedPayload":{"position":{"x":11245.31760010297,"y":19132.987954698667},"targetPosition":{"x":11779.92151461599,"y":18860.59365485494},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"20fcfc66-d336-4c0d-872f-50a5d8cd50b6","savedPayload":{"position":{"x":11811.493133483104,"y":18891.553385199248},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"bullPriceDeviation","config":"{\n \"codeName\": \"bullPriceDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.bullPriceDeviation)) {\nvariable.bullPriceDeviation\n}\nelse {\nvariable.bullPriceDeviation = 1\n}","project":"Superalgos","id":"fa9aa35e-98af-416d-b3b9-395327e5cd9d","savedPayload":{"position":{"x":11925.045623569087,"y":18640.3908017439},"targetPosition":{"x":12074.441767668373,"y":18653.836698079413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7bd05b9a-a315-4e3d-93b0-3943a7f3ba50","savedPayload":{"position":{"x":12074.441767668373,"y":18653.836698079413},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"smaPrice","config":"{\n \"codeName\": \"smaPrice\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.smaPrice)) {\nvariable.smaPrice\n}\nelse {\nvariable.smaPrice = 1\n}","project":"Superalgos","id":"63142088-1b62-4a15-985f-c53cd6adb314","savedPayload":{"position":{"x":11986.932098746105,"y":18449.923815917784},"targetPosition":{"x":12115.699417786385,"y":18526.85870752867},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"67b38c00-0e3d-47bc-942c-0fdda9625e9a","savedPayload":{"position":{"x":12115.699417786385,"y":18526.85870752867},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"volumeDeviation","config":"{\n \"codeName\": \"volumeDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.volumeDeviation)) {\nvariable.volumeDeviation\n}\nelse {\nvariable.volumeDeviation = 1\n}","project":"Superalgos","id":"6ec8c68a-20f5-4d3d-8ef5-1c0e87f0c5a3","savedPayload":{"position":{"x":12125.3304142135,"y":18305.170526575857},"targetPosition":{"x":12207.964961431315,"y":18430.35651463405},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"aa0f2fc4-d1de-49d8-87cb-d2d68b4bbb09","savedPayload":{"position":{"x":12207.964961431315,"y":18430.35651463405},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"openInterestDeviation","config":"{\n \"codeName\": \"openInterestDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.openInterestDeviation)) {\nvariable.openInterestDeviation\n}\nelse {\nvariable.openInterestDeviation = 1\n}","project":"Superalgos","id":"3fde42f1-88e4-4a07-9f0d-ad1ceef8ae89","savedPayload":{"position":{"x":12312.829086249,"y":18234.80109795487},"targetPosition":{"x":12332.964076121649,"y":18383.44356222006},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"264be2f7-a27c-414b-8aee-7473c120b89f","savedPayload":{"position":{"x":12332.964076121649,"y":18383.44356222006},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"536bed44-cdea-4518-974c-4fbd6787c969","savedPayload":{"position":{"x":12373.234055866946,"y":18680.728490750444},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"EDIT TOP LINES HERE TO CHANGE PERIODS","code":"// The Average VS Average Oscillator\n\n/* The Average VS Average Oscillator can be used to recognize changes between a fast average ('fastPeriod') and a slow average ('slowPeriod'). It measures 'Price Action', 'Volume', and a so called 'Open Interest'.\n'Bull Price Action' and 'Bear Price Action' is defined by the amount between the candle close and max and min.\n'Bull Volume' and 'Bear Volume' is divided using the price action.\n'Open Interest' is based upon the statement where:\nBull Candle and Volume Increase = Bull Interest\nBull Candle and Volume Decrease = Bear Interest\nBear Candle and Volume Increase = Bear Interest\nBear Candle and Volume Decrease = Bull Interest */\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n/* USER DEFINED VALUES SECTION */\n\nlet fastPeriod = 5 // Change this number to the period of your choice (must be less than 'slowPeriod')\nlet slowPeriod = 21 // Change this number to the period of your choice (must be greater than 'fastPeriod')\nlet periodMultiplier = 3 // The 'slowPeriod' is muliplied by the 'periodMultiplier to create the \"long term\" trend\nlet fastBoost = 1.00 // '1.00' equals 'no extra boost' to your 'fastPeriod' where as '1.23' would boost the value by 23%\nlet gravity = 0 // '0' equals 'no gravity' (pullback towards midline ('slowPeriod'))\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring variables used\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \nlet volCandle = record.current\nlet volume = getElement('volumes', volCandle)\nlet totalVolume = volume.buy + volume.sell\nlet totalRange = candle.max - candle.min\nlet multipliedFast = fastPeriod * periodMultiplier\nlet multipliedSlow = slowPeriod * periodMultiplier\n\nif ( candle.close > candle.open ) { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\nelse { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Volume Difference'\n\nvariable.previousCurrentVolume.push(totalVolume)\nif (variable.previousCurrentVolume.length > 2) {\n variable.previousCurrentVolume.splice(0, 1)\n}\n\nif (variable.previousCurrentVolume[1] === 'undefined') {\n variable.positiveVolumeDifference = 0.01\n}\nelse {\n if (variable.previousCurrentVolume[variable.previousCurrentVolume.max] > variable.previousCurrentVolume[0]) {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[1] - variable.previousCurrentVolume[0]) \n }\n else {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[0] - variable.previousCurrentVolume[1])\n }\n}\n\nvariable.bullVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bullPriceRange / totalRange)\nvariable.bearVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bearPriceRange / totalRange)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Open Interest'\n// Converting values to percentages due to the differences of range and volume (range might be in decimals while volume often is in thousands)\n\nif ( candle.close > candle.open && variable.previousCurrentVolume[1] > variable.previousCurrentVolume[0] ) { // Candle UP & Volume UP, Bullish Interest\n variable.openInterest = 1 + ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close < candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle DOWN & Volume DOWN, Bullish Interest\n variable.openInterest = 1 + ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close > candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle UP & Volume DOWN, Bearish Interest\n variable.openInterest = 1 - ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse { // Candle DOWN & Volume UP, Bearish Interest\n variable.openInterest = 1 - ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Saving to arrays\n\nvariable.savedCandleClose.push(candle.close)\nif (variable.savedCandleClose.length > multipliedSlow) {\n variable.savedCandleClose.splice(0, 1)\n}\n\nvariable.savedTotalRange.push(totalRange)\nif (variable.savedTotalRange.length > multipliedSlow) {\n variable.savedTotalRange.splice(0, 1)\n}\n\nvariable.savedBullPriceRange.push(variable.bullPriceRange)\nif (variable.savedBullPriceRange.length > multipliedSlow) {\n variable.savedBullPriceRange.splice(0, 1)\n}\n\nvariable.savedTotalVolume.push(totalVolume)\nif (variable.savedTotalVolume.length > multipliedSlow) {\n variable.savedTotalVolume.splice(0, 1)\n}\n\nvariable.savedOpenInterest.push(variable.openInterest)\nif (variable.savedOpenInterest.length > multipliedSlow) {\n variable.savedOpenInterest.splice(0, 1)\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Calling SMA functions\n\nvariable.smaMultipliedFastCandleClose = calculateSMA(variable.savedCandleClose, multipliedFast)\nvariable.smaSlowCandleClose = calculateSMA(variable.savedCandleClose, slowPeriod)\nvariable.smaLongTermCandleClose = calculateSMA(variable.savedCandleClose, multipliedSlow)\n\nvariable.smaFastTotalRange = calculateSMA(variable.savedTotalRange, fastPeriod)\nvariable.smaSlowTotalRange = calculateSMA(variable.savedTotalRange, slowPeriod)\nvariable.smaLongTermRange = calculateSMA(variable.savedTotalRange, multipliedSlow)\n\nvariable.smaFastBullPriceRange = calculateSMA(variable.savedBullPriceRange, fastPeriod)\nvariable.smaSlowBullPriceRange = calculateSMA(variable.savedBullPriceRange, slowPeriod)\n\nvariable.smaFastTotalVolume = calculateSMA(variable.savedTotalVolume, fastPeriod)\nvariable.smaLongTermTotalVolume = calculateSMA(variable.savedTotalVolume, multipliedSlow)\n\nvariable.smaFastOpenInterest = calculateSMA(variable.savedOpenInterest, fastPeriod)\nvariable.smaSlowOpenInterest = calculateSMA(variable.savedOpenInterest, slowPeriod)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Creating the SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calculation\n if (src.length < periods) { return 0 }\n \n // Initialize sum variable\n let sum = 0 \n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring record variables by comparing 'fastPeriod' values with 'slowPeriod' values, also applying 'fastBoost' and 'gravity'\n\nvariable.fastPriceRange = variable.smaFastTotalRange\nvariable.slowPriceRange = variable.smaSlowTotalRange\nvariable.longTermPriceRange = variable.smaLongTermRange\n\nvariable.bullPriceDeviation = ((((variable.smaFastBullPriceRange * fastBoost) + (variable.smaSlowBullPriceRange * gravity)) / (gravity + 1)) / variable.slowPriceRange) * 2\n\nvariable.volumeDeviation = variable.smaFastTotalVolume / variable.smaLongTermTotalVolume\n\nvariable.openInterestDeviation = ((((variable.smaFastOpenInterest * fastBoost) + (variable.smaSlowOpenInterest * gravity)) / (gravity + 1)) / variable.smaSlowOpenInterest)\n\nvariable.smaPrice = variable.smaMultipliedFastCandleClose / variable.smaLongTermCandleClose\n\n// Happy trading! CJ.","project":"Superalgos","id":"8c60ba71-a9d3-4f8e-afe0-896444288364","savedPayload":{"position":{"x":12573.245899592053,"y":18466.10349130047},"targetPosition":{"x":12650.96049573775,"y":18529.035530405454},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a063882c-12d0-4d12-9b5a-ca5b1db72b7f","savedPayload":{"position":{"x":12650.96049573775,"y":18529.035530405454},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 6 arrays \n\nvariable.previousCurrentVolume = []\nvariable.savedTotalRange = []\nvariable.savedBullPriceRange = [] \nvariable.savedTotalVolume = [] \nvariable.savedOpenInterest = [] \nvariable.savedCandleClose = [] ","project":"Superalgos","id":"34d8c2bd-b8fc-4584-9d03-262c2ed57243","savedPayload":{"position":{"x":12677.94040256997,"y":18390.038482438627},"targetPosition":{"x":12713.7771975245,"y":18483.39652508835},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7aab7dde-e3ed-45b0-907e-f7e7ca67c900","savedPayload":{"position":{"x":12713.7771975245,"y":18483.39652508835},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"59f62f92-018d-4f53-9c86-efa887cad1ce","savedPayload":{"position":{"x":12767.532389956295,"y":18623.43358906293},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"331e099d-5ffe-4d60-8186-effe0aef5d17","savedPayload":{"position":{"x":12943.867965644038,"y":18866.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Average VS Average","id":"13acaaae-6a8e-4e48-a326-9d209079629f"}}}],"id":"01b8702d-ee62-45f7-ac01-e1f7ce70c843","savedPayload":{"position":{"x":13243.867965644038,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"plotters":[{"type":"Plotter","name":"Chaikin Oscillator Plotter","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.zeroLine","project":"Superalgos","id":"80862799-63a8-4ba6-a807-b8425ebf42e6","savedPayload":{"position":{"x":12437.728644668177,"y":19458.751691732494},"targetPosition":{"x":12390.798305156108,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ef40ac92-9977-4887-9c81-b2442254f267","savedPayload":{"position":{"x":12390.798305156108,"y":19162.445189553953},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.zeroLine","project":"Superalgos","id":"926f7d83-fec5-4224-b5a4-8e1a54520950","savedPayload":{"position":{"x":12071.473665800311,"y":19400.742601888433},"targetPosition":{"x":12207.670815722175,"y":19133.440644631923},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47","savedPayload":{"position":{"x":12207.670815722175,"y":19133.440644631923},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.chaikinOscillator","project":"Superalgos","id":"e741c1f0-43b2-4863-8d93-7fc46b343d93","savedPayload":{"position":{"x":11809.264051131018,"y":19138.53298721914},"targetPosition":{"x":12076.566008387528,"y":19002.335837297276},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"53915588-afe8-48a8-9d68-5726ff873676","savedPayload":{"position":{"x":12076.566008387528,"y":19002.335837297276},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.chaikinOscillator","project":"Superalgos","id":"10fc95bd-dc19-407a-809e-6f4f385316f6","savedPayload":{"position":{"x":11751.254961286957,"y":18772.278008351273},"targetPosition":{"x":12047.561463465498,"y":18819.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8","savedPayload":{"position":{"x":12047.561463465498,"y":18819.208347863343},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b2a71e98-e51b-4b89-972e-d5581f4625e0","savedPayload":{"position":{"x":12343.867965644038,"y":18866.138687375413},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"246dfad4-544c-47fb-8b84-977bdd41cd47","savedPayload":{"position":{"x":14463.44450422656,"y":16854.484741416603},"targetPosition":{"x":14753.22225211328,"y":16932.13045494736},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8896e73d-ee20-461b-9608-55f4927c4b10","savedPayload":{"position":{"x":14753.22225211328,"y":16932.13045494736},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"163aeab0-ae3e-4467-9da4-9f96dc09ec0f","savedPayload":{"position":{"x":14893.000000000002,"y":16749.968547342785},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"ef40ac92-9977-4887-9c81-b2442254f267"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"e1f60b5e-6727-44d7-8e9c-d913098cd747","savedPayload":{"position":{"x":15120.64571353076,"y":16719.998420591397},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47"}}}],"id":"f79ac980-28be-4eaf-87ee-0ae394c976eb","savedPayload":{"position":{"x":12256.000000000002,"y":18654.00665301945},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"Chaikin Oscillator","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"60001259-de7c-4c30-b752-839c3ec0cd10","savedPayload":{"position":{"x":11743.867965644038,"y":18441.874618663485},"targetPosition":{"x":12043.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7dcea241-9bf6-4dcd-99d5-f568e8ebd151","savedPayload":{"position":{"x":12043.867965644038,"y":18441.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Chaikin Oscillator Begin","project":"Superalgos","id":"9efb3b5e-4eeb-4aa8-a18e-bada560c738f","savedPayload":{"position":{"x":12131.735931288074,"y":18229.74258430752},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator Begin","id":"53915588-afe8-48a8-9d68-5726ff873676"}}},{"type":"Polygon Vertex","name":"Chaikin Oscillator End","project":"Superalgos","id":"08067dd0-d1a3-4b75-bcee-996118cfd9db","savedPayload":{"position":{"x":12343.867965644038,"y":18141.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator End","id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8"}}}],"id":"b5dd57fb-a9cc-48f2-bc06-cb3b02544f08","savedPayload":{"position":{"x":12343.867965644038,"y":18441.874618663485},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"d4571993-801c-4a30-9fc9-eac333de1451","savedPayload":{"position":{"x":12556.000000000002,"y":18654.00665301945},"targetPosition":{"x":12856.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae","savedPayload":{"position":{"x":12856.000000000002,"y":18654.00665301945},"targetPosition":{"x":13156.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"9639a20f-b875-46f6-8cbb-4e71cc941041","savedPayload":{"position":{"x":13156.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Slow Plotter","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"a210d685-38e1-43a3-9878-adbd61c761e0","savedPayload":{"position":{"x":15538.752452292845,"y":18825.3271911492},"targetPosition":{"x":15238.886722607795,"y":18816.35255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e","savedPayload":{"position":{"x":15238.886722607795,"y":18816.35255129838},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"b884cd0e-265e-4f70-846f-33a37a257ecc","savedPayload":{"position":{"x":15471.572466325475,"y":19083.76338171794},"targetPosition":{"x":15205.296729624106,"y":18945.57064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5","savedPayload":{"position":{"x":15205.296729624106,"y":18945.57064658275},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"eb99829a-5d1a-40e4-9ccc-7fc73d6c6948","savedPayload":{"position":{"x":15298.914129735489,"y":19287.45804025429},"targetPosition":{"x":15118.967561329113,"y":19047.417975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2852ef63-8ffe-4516-b5f9-f635ea773efa","savedPayload":{"position":{"x":15118.967561329113,"y":19047.417975850924},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"8aedf7aa-675e-467b-b9b5-d60754399725","savedPayload":{"position":{"x":15054.974543600074,"y":19396.066941484063},"targetPosition":{"x":14996.997768261406,"y":19101.72242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"66be2c9a-b271-4410-b305-d6ff7a8f6806","savedPayload":{"position":{"x":14996.997768261406,"y":19101.72242646581},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"4db679ee-e6b7-43e0-89b9-df275970ab75","savedPayload":{"position":{"x":14788.068934676035,"y":19388.07876051796},"targetPosition":{"x":14863.544963799388,"y":19097.728335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31","savedPayload":{"position":{"x":14863.544963799388,"y":19097.728335982767},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"f68cafa6-18dd-40b8-b669-265897ffbbc7","savedPayload":{"position":{"x":14551.061232193262,"y":19265.075654564916},"targetPosition":{"x":14745.041112558001,"y":19036.226783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e","savedPayload":{"position":{"x":14745.041112558001,"y":19036.226783006245},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"0fbe8beb-9d62-46b2-9d77-9b246aff6bdc","savedPayload":{"position":{"x":12634.447798537763,"y":18587.46242578744},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95265ad5-3c49-4d1f-9a60-01bcdf2816be","savedPayload":{"position":{"x":15081.40991376369,"y":19329.96089514218},"targetPosition":{"x":14918.01820325918,"y":19078.359724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d3facbf8-a2e6-4452-b21b-35352511a827","savedPayload":{"position":{"x":14918.01820325918,"y":19078.359724758553},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"36c97105-26c3-475e-949d-ce8c3480f651","savedPayload":{"position":{"x":14692.252985509345,"y":19120.202834595064},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"6dd790c5-abf3-4fb3-b19f-6afaf91da40a","savedPayload":{"position":{"x":14503.025322371046,"y":18990.15026487943},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5"}}}],"id":"c92be7eb-fddc-4bc6-a65d-a0a40bc37ec8","savedPayload":{"position":{"x":12490.357013017727,"y":18470.780008342786},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95ed4962-8fe8-4f35-ae47-64204481b727","savedPayload":{"position":{"x":14562.654978611015,"y":19333.231176915182},"targetPosition":{"x":14578.355765483899,"y":19033.642316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"e7445d37-5968-48de-927c-4efdb45b7c59","savedPayload":{"position":{"x":14578.355765483899,"y":19033.642316488807},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"0f784377-cb5c-4f2f-96b3-68407b05af78","savedPayload":{"position":{"x":14371.113104713564,"y":18934.7926379701},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"2852ef63-8ffe-4516-b5f9-f635ea773efa"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"8c0f843b-249e-4a35-88b9-70f63e1890c3","savedPayload":{"position":{"x":14294.46769193041,"y":18718.352669189557},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"66be2c9a-b271-4410-b305-d6ff7a8f6806"}}}],"id":"f019e42a-3005-4a2b-9717-48d6902c03da","savedPayload":{"position":{"x":12442.36932297498,"y":18291.687510965396},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"b3ea885c-fc4e-44b5-93e4-c965b7622d6d","savedPayload":{"position":{"x":14141.051196759618,"y":19030.96039000926},"targetPosition":{"x":14329.847314074568,"y":18797.81660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"a1fa021f-4b0f-41ee-a344-cdb8360b641a","savedPayload":{"position":{"x":14329.847314074568,"y":18797.81660157217},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"1c703412-aa66-4f3c-953e-f1798935a713","savedPayload":{"position":{"x":14220.286862779038,"y":18596.031352115377},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"e915dba3-f07e-42df-9705-7da67057decd","savedPayload":{"position":{"x":14285.499642952427,"y":18375.876695820127},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e"}}}],"id":"07d9669b-ce23-49fb-b2dd-666c5f32c755","savedPayload":{"position":{"x":12508.814394964262,"y":18118.592180523327},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"59717ffa-8d07-4e2b-98da-e6fb3353ea04","savedPayload":{"position":{"x":12741.958183401353,"y":18307.38829783828},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"6f7acaa5-1243-4f77-875f-5397475358e9","savedPayload":{"position":{"x":12699.574023683499,"y":17530.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c1de33b9-fa92-419f-baa8-081dc437c569","savedPayload":{"position":{"x":12959.38164481883,"y":17380.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8fd22998-6471-490b-bd96-9d30d99978b8","savedPayload":{"position":{"x":12959.38164481883,"y":17680.157215285468},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"20fc3099-2c91-4c55-9336-60553f207253","savedPayload":{"position":{"x":13109.38164481883,"y":17360.40934064736},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"6906425e-38ab-4aaa-84da-b4e43eda38cd","savedPayload":{"position":{"x":13399.15939270555,"y":17438.055054178116},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b9bd72d6-fe20-411e-a481-3593020f9ee2","savedPayload":{"position":{"x":13187.027358349585,"y":17650.18708853408},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"457c2cc9-cf06-407d-a12b-e9a24ce43a3b","savedPayload":{"position":{"x":13519.18926595416,"y":17530.157215285468},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"8d54d8bf-89eb-41f8-bfb2-8a471506b3b5","savedPayload":{"position":{"x":13669.18926595416,"y":17789.9648364208},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2731ea97-36e9-4bad-8339-803c567e8a87","savedPayload":{"position":{"x":13369.18926595416,"y":17789.9648364208},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"75e49a63-45a5-4f16-876e-53a509ddb245","savedPayload":{"position":{"x":13109.38164481883,"y":17939.9648364208},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e12e90bd-bc37-42da-9f83-7b1506391bd9","savedPayload":{"position":{"x":13031.735931288074,"y":18229.74258430752},"targetPosition":{"x":13243.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f3a68e45-18b6-4192-bccd-00364c5d72c0","savedPayload":{"position":{"x":13243.867965644038,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Fast Plotter","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"7f32a7cc-bbbb-4b76-918d-fb4b49ae1cbe","savedPayload":{"position":{"x":15614.752452292845,"y":18600.8271911492},"targetPosition":{"x":15314.886722607795,"y":18591.85255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"43c595ce-8ba1-4a6a-b126-38898e46c880","savedPayload":{"position":{"x":15314.886722607795,"y":18591.85255129838},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"17b6dd00-6205-482f-8ed4-1c7b215aa634","savedPayload":{"position":{"x":15547.572466325475,"y":18859.26338171794},"targetPosition":{"x":15281.296729624106,"y":18721.07064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d","savedPayload":{"position":{"x":15281.296729624106,"y":18721.07064658275},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"c65449b6-1047-449c-8974-d439b263f767","savedPayload":{"position":{"x":15374.914129735489,"y":19062.95804025429},"targetPosition":{"x":15194.967561329117,"y":18822.917975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade","savedPayload":{"position":{"x":15194.967561329117,"y":18822.917975850924},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"bf788df7-d7bd-44f5-a1e2-f991b559eb67","savedPayload":{"position":{"x":15130.974543600076,"y":19171.566941484063},"targetPosition":{"x":15072.997768261408,"y":18877.22242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58","savedPayload":{"position":{"x":15072.997768261408,"y":18877.22242646581},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"e4644710-8f0c-462d-b981-a1dce5b8c73a","savedPayload":{"position":{"x":14864.068934676037,"y":19163.57876051796},"targetPosition":{"x":14939.54496379939,"y":18873.228335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a144fd80-7187-4237-8a1e-efc6927eb58f","savedPayload":{"position":{"x":14939.54496379939,"y":18873.228335982767},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"c31177a2-ed80-4eab-9b17-b4a6a17fd77a","savedPayload":{"position":{"x":14627.061232193264,"y":19040.575654564916},"targetPosition":{"x":14821.041112558003,"y":18811.726783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"725734c1-1636-4802-a3d7-40caa4b4f655","savedPayload":{"position":{"x":14821.041112558003,"y":18811.726783006245},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ddc7e432-cf87-475e-8af1-ddd2209fde78","savedPayload":{"position":{"x":12922.12874157189,"y":18026.027645942188},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"25a3b187-cb00-4569-881a-e8599a2ac9bf","savedPayload":{"position":{"x":15157.40991376369,"y":19105.46089514218},"targetPosition":{"x":14994.018203259182,"y":18853.859724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7807b9a3-05ea-421c-8584-d363dff6ca7a","savedPayload":{"position":{"x":14994.018203259182,"y":18853.859724758553},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"498ac6aa-2b55-4793-b2fe-0fd647ae7512","savedPayload":{"position":{"x":14768.252985509347,"y":18895.702834595064},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"43c595ce-8ba1-4a6a-b126-38898e46c880"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"f65fd57b-fd01-440e-a825-098fff6c4952","savedPayload":{"position":{"x":14579.025322371048,"y":18765.65026487943},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d"}}}],"id":"d481800e-4a37-4638-a095-e03282974b8d","savedPayload":{"position":{"x":12902.74809864453,"y":17841.63314577412},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"8463545a-e7e6-46d1-975c-729f23eaa7d2","savedPayload":{"position":{"x":14638.654978611017,"y":19108.731176915182},"targetPosition":{"x":14654.3557654839,"y":18809.142316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"0fbd4479-d451-4f8a-8452-27171db16d82","savedPayload":{"position":{"x":14654.3557654839,"y":18809.142316488807},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"63eacfe5-505a-4634-bb5e-c63214b48ebd","savedPayload":{"position":{"x":14447.113104713566,"y":18710.2926379701},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"eed08a75-d991-4dd6-98d1-6e0ee70dd04e","savedPayload":{"position":{"x":14370.467691930411,"y":18493.852669189557},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58"}}}],"id":"3bfca508-8cbb-4bad-8473-b0e8d785069e","savedPayload":{"position":{"x":12995.453196957013,"y":17681.06320537623},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"a280c06f-5e9c-44b4-906c-0bd88866c1e4","savedPayload":{"position":{"x":14217.05119675962,"y":18806.46039000926},"targetPosition":{"x":14405.84731407457,"y":18573.31660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"ff24e3b0-c186-4d2b-8722-e19f72075d41","savedPayload":{"position":{"x":14405.84731407457,"y":18573.31660157217},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"cffa95e0-222b-46da-b1db-5ca83d0dc237","savedPayload":{"position":{"x":14296.28686277904,"y":18371.531352115377},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"a144fd80-7187-4237-8a1e-efc6927eb58f"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"adc73235-49b3-4e74-a451-0a4ba69e0547","savedPayload":{"position":{"x":14361.499642952429,"y":18151.376695820127},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"725734c1-1636-4802-a3d7-40caa4b4f655"}}}],"id":"c6488672-2e9b-43a6-b6de-a398ea651320","savedPayload":{"position":{"x":13164.833839884375,"y":17605.650084408968},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"4ff7b240-bdd0-4f1d-8e31-5f9084686c69","savedPayload":{"position":{"x":13196.19237886467,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"4fae804c-e7d9-4f8f-9441-59e26185fff7","savedPayload":{"position":{"x":13715.807621135333,"y":17324.451157246007},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c5312c7b-f55e-43b7-943e-902588c25c9b","savedPayload":{"position":{"x":14005.585369022052,"y":17402.096870776764},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cdda2164-3e6b-4817-acbc-891388443917","savedPayload":{"position":{"x":13793.453334666088,"y":17614.228905132728},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"b9258e5a-1bef-4144-b489-3a65a5c867af","savedPayload":{"position":{"x":14125.615242270664,"y":17494.199031884116},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"9a9c7c68-f24e-4c5e-9e29-34b8260df057","savedPayload":{"position":{"x":14275.615242270664,"y":17754.00665301945},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2ce1a18f-aa45-4b1e-a01b-2125ebf93c8e","savedPayload":{"position":{"x":13975.615242270664,"y":17754.00665301945},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"ea88a867-d92e-4680-a40b-ec580bd80df2","savedPayload":{"position":{"x":14295.363116908775,"y":17904.00665301945},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"6430bee3-15e0-4598-a686-2ebc5f4ec6f5","savedPayload":{"position":{"x":14217.717403378017,"y":18193.78440090617},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"39efdc4e-0784-48c0-a39b-0dc54548cb77","savedPayload":{"position":{"x":14005.585369022054,"y":17981.652366550206},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"775abeea-a292-46a5-aebb-f8c0bfef7ca0","savedPayload":{"position":{"x":13715.807621135333,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"fdffbdff-a42f-47db-b068-4a711070bef3","savedPayload":{"position":{"x":13456.000000000002,"y":18054.00665301945},"targetPosition":{"x":13456.000000000002,"y":18354.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"5a1c468b-1e45-414b-8710-952a78fe831c","savedPayload":{"position":{"x":13456.000000000002,"y":18354.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Average VS Average Plotter","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = 1","project":"Superalgos","id":"80edad17-0f41-4dbb-864e-c2b257b06dde","savedPayload":{"position":{"x":13012.422735946908,"y":17744.918604065882},"targetPosition":{"x":13457.320310615743,"y":17677.345324925474},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c695315b-a12a-4972-8363-a3812215a54e","savedPayload":{"position":{"x":13457.320310615743,"y":17677.345324925474},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = 1","project":"Superalgos","id":"bf6adc6e-9aaf-434a-a41d-12a97f076653","savedPayload":{"position":{"x":13010.390506126048,"y":17488.75995637569},"targetPosition":{"x":13456.304195705314,"y":17549.266001080377},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c","savedPayload":{"position":{"x":13456.304195705314,"y":17549.266001080377},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.bullPriceDeviation","project":"Superalgos","id":"52a0dcca-d50d-4dfa-adb0-d6a2d2593187","savedPayload":{"position":{"x":13080.608826662963,"y":17242.404988482835},"targetPosition":{"x":13491.413355973771,"y":17426.08851713395},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf","savedPayload":{"position":{"x":13491.413355973771,"y":17426.08851713395},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.bullPriceDeviation","project":"Superalgos","id":"18676f64-51d5-4480-8ca7-398a8cf45098","savedPayload":{"position":{"x":13217.389026832188,"y":17025.81191475659},"targetPosition":{"x":13559.803456058384,"y":17317.791980270827},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f","savedPayload":{"position":{"x":13559.803456058384,"y":17317.791980270827},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.volumeDeviation","project":"Superalgos","id":"9cf7a19a-ff50-46ca-86c3-f8412d4e53ee","savedPayload":{"position":{"x":13409.64998827918,"y":16856.527817901653},"targetPosition":{"x":13655.93393678188,"y":17233.14993184336},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19","savedPayload":{"position":{"x":13655.93393678188,"y":17233.14993184336},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.volumeDeviation","project":"Superalgos","id":"c14b45db-6a55-4b02-83d3-f9c758bcdbde","savedPayload":{"position":{"x":13641.815871327472,"y":16748.267088673914},"targetPosition":{"x":13772.016878306025,"y":17179.01956722949},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82","savedPayload":{"position":{"x":13772.016878306025,"y":17179.01956722949},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.openInterestDeviation","project":"Superalgos","id":"afc254ff-402b-4632-952a-3a8504eb2f11","savedPayload":{"position":{"x":13895.07797687616,"y":16709.800367504067},"targetPosition":{"x":13898.64793108037,"y":17159.786206644567},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"803aaa7c-ad01-4bad-9943-f4fac99e4987","savedPayload":{"position":{"x":13898.64793108037,"y":17159.786206644567},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.openInterestDeviation","project":"Superalgos","id":"2d21a7f4-e6ea-47c2-85ec-4638fd68d0bd","savedPayload":{"position":{"x":14148.91851534143,"y":16744.243999370883},"targetPosition":{"x":14025.568200313004,"y":17177.008022577975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2","savedPayload":{"position":{"x":14025.568200313004,"y":17177.008022577975},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.smaPrice","project":"Superalgos","id":"d2a3c177-7426-4111-9e6e-80bd2ddd2ecc","savedPayload":{"position":{"x":14382.77283594463,"y":16848.80756606468},"targetPosition":{"x":14142.495360614605,"y":17229.289805924873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"de30fcce-febc-4c65-8908-852b2c91a3d9","savedPayload":{"position":{"x":14142.495360614605,"y":17229.289805924873},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.smaPrice","project":"Superalgos","id":"0bfdd80f-4420-4333-a60e-ac5afe17df21","savedPayload":{"position":{"x":14577.695452415694,"y":17015.01994927541},"targetPosition":{"x":14239.956668850136,"y":17312.39599753024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2","savedPayload":{"position":{"x":14239.956668850136,"y":17312.39599753024},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f20cacf7-c7ce-4a35-a06d-15951850e570","savedPayload":{"position":{"x":13902.21788528458,"y":17609.772045785066},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"62cd1b53-a0fd-4f09-a9c0-9bb7ac3ac642","savedPayload":{"position":{"x":13606.622714372208,"y":17333.07957471211},"targetPosition":{"x":13836.436047307901,"y":17525.91585761807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8eca09c2-69dc-4768-b3e4-08fa7f68b8e6","savedPayload":{"position":{"x":13836.436047307901,"y":17525.91585761807},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"af6872e7-8d5d-451e-802c-de5f614ea534","savedPayload":{"position":{"x":14040.102657419297,"y":17419.89373109651},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"9bfa8714-fe8d-4631-b9ca-8236b9f989b7","savedPayload":{"position":{"x":14259.085663149557,"y":17488.93880758834},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}}],"id":"ed0185c6-e131-4acf-983c-8ddfe5f1c523","savedPayload":{"position":{"x":14066.249380243595,"y":17718.752140524033},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice > record.previous.smaPrice","project":"Superalgos","id":"6f7dcb6c-ae19-46b2-a082-916dae93a16b","savedPayload":{"position":{"x":14003.00510583763,"y":16806.807443877766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"5860dc00-e1a5-4c65-bd4e-843091d935ce","savedPayload":{"position":{"x":13702.103077599852,"y":16642.91315569686},"targetPosition":{"x":13998.409579778392,"y":16689.843495208926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"675151a8-9c7d-4c48-860d-00e52056eec5","savedPayload":{"position":{"x":13998.409579778392,"y":16689.843495208926},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bf8ec324-5a02-4895-80ac-46fd519aa77c","savedPayload":{"position":{"x":13783.131983344476,"y":16423.274695891418},"targetPosition":{"x":14038.924032650704,"y":16580.024265306205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f7367289-76e5-48d5-a910-0c6636e8869c","savedPayload":{"position":{"x":14038.924032650704,"y":16580.024265306205},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"a74fa0b1-3291-4e48-a1e2-6fed290b521e","savedPayload":{"position":{"x":14118.38050626919,"y":16494.068736408506},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"33d6f2c5-3db4-42ce-8766-f408840b78e0","savedPayload":{"position":{"x":14224.682472800161,"y":16445.062858601686},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8ca3ff70-71b8-41a7-b184-2d85d95c29f4","savedPayload":{"position":{"x":14341.646421469002,"y":16440.46733254245},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"b711c638-8290-4d76-a1f4-96a9019c6b3d","savedPayload":{"position":{"x":14451.465651371718,"y":16480.981785414766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"a7e542dd-3221-4a1a-ab83-16a44d001416","savedPayload":{"position":{"x":14170.041816598648,"y":17727.832802064837},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice < record.previous.smaPrice","project":"Superalgos","id":"da6fa977-095e-439d-90a2-7e226c210bd1","savedPayload":{"position":{"x":14090.2888941966,"y":16657.139460121613},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"9e2a011a-4aa8-463c-a10c-dd18e0534a50","savedPayload":{"position":{"x":13863.588626615938,"y":16400.214652104183},"targetPosition":{"x":14125.974538757757,"y":16545.657538178082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d395d4a9-883b-49e9-90ae-a83f2fe2f59d","savedPayload":{"position":{"x":14125.974538757757,"y":16545.657538178082},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"941bac99-ea7f-4f0f-b149-3cf34f766cb0","savedPayload":{"position":{"x":14014.851668917005,"y":16221.535530140533},"targetPosition":{"x":14201.60605990829,"y":16456.317977196257},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"2ce85b80-0291-4b52-a297-72dd5e780d6e","savedPayload":{"position":{"x":14201.60605990829,"y":16456.317977196257},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"775e669a-6800-4190-9cad-dbae717911f5","savedPayload":{"position":{"x":14305.669244154476,"y":16402.721915470484},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"0a680163-5643-4a13-b55b-5fb80edde733","savedPayload":{"position":{"x":14422.321415029948,"y":16393.028867549005},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"cb32f3a6-681d-4df5-bdfc-14270081099b","savedPayload":{"position":{"x":14533.803336973477,"y":16428.71451211016},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"e50f0167-e004-4f8a-b593-1729a14e7c0d","savedPayload":{"position":{"x":14623.1428979553,"y":16504.346033260696},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"57807fe3-2d38-4767-8cee-b0d9091d358e","savedPayload":{"position":{"x":14264.469033973206,"y":17771.86493666486},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation > record.previous.volumeDeviation","project":"Superalgos","id":"5579428b-bd6e-44f1-b53a-9b9b9948b091","savedPayload":{"position":{"x":14231.426213757817,"y":16531.507148561304},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bbe1b239-e08b-440e-971a-49c3ee92a19a","savedPayload":{"position":{"x":14151.518676912645,"y":16186.158059796802},"targetPosition":{"x":14321.74863834028,"y":16433.183888876167},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"826e811a-3650-45c8-914d-b9cdb25c7624","savedPayload":{"position":{"x":14321.74863834028,"y":16433.183888876167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"4393fca4-e15d-4170-a127-5862e8c845a2","savedPayload":{"position":{"x":14445.787194516954,"y":16383.787124213184},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8c390826-ef92-470f-bd4f-4fb5aa2995a6","savedPayload":{"position":{"x":14578.97452500399,"y":16393.100489625405},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"aa9b0281-5501-4ecf-8747-03df65df1b82","savedPayload":{"position":{"x":14694.931245563015,"y":16459.27935887202},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"114e6dce-ec3c-4ab1-b7f4-5f72f36eeabb","savedPayload":{"position":{"x":14770.690705571464,"y":16569.216195268167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"d42bf0ab-d03e-4a30-a896-d27fdbe4fa98","savedPayload":{"position":{"x":14338.14171635459,"y":17845.537619046245},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation < record.previous.volumeDeviation","project":"Superalgos","id":"ba7ccc38-7438-4fd9-8d17-1f7d1c4bff39","savedPayload":{"position":{"x":14157.277178666109,"y":16579.923368208143},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"43749c18-0468-43de-9198-abb8d04541dc","savedPayload":{"position":{"x":14018.614376933985,"y":16253.69670625219},"targetPosition":{"x":14229.153747799182,"y":16467.409535337592},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"1c2a8a8c-9619-43e6-b564-f478e699a656","savedPayload":{"position":{"x":14229.153747799182,"y":16467.409535337592},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"564d9677-fff2-429f-8dd1-61233ab23d60","savedPayload":{"position":{"x":14342.73022142804,"y":16397.224149283244},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"7aacc15f-eba7-4455-a74a-23ba60467128","savedPayload":{"position":{"x":14475.511386026454,"y":16383.268286520444},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"9b74661e-c05a-4407-9e2d-f387f2b439e2","savedPayload":{"position":{"x":14601.198303491585,"y":16428.30607682678},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"478698e3-2c63-421d-b25c-bd6e641d76a2","savedPayload":{"position":{"x":14694.897138370581,"y":16523.417233479846},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"fb723dee-63a8-46c2-afc4-48210897864c","savedPayload":{"position":{"x":14382.173850954614,"y":17939.9648364208},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"openInterestDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 2,\n 7\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"30cdd628-da04-4589-b126-db7da41f9b45","savedPayload":{"position":{"x":14668.977724920003,"y":16163.768375838048},"targetPosition":{"x":14674.213446851189,"y":16463.722684384968},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"5ea53d11-e359-484f-920c-76c642c44018","savedPayload":{"position":{"x":14674.213446851189,"y":16463.722684384968},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"openInterestDeviation Begin","project":"Superalgos","id":"39e8c351-78ce-4df3-abd0-24512243c73a","savedPayload":{"position":{"x":14887.846679920072,"y":16547.875052830295},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation Begin","id":"803aaa7c-ad01-4bad-9943-f4fac99e4987"}}},{"type":"Polygon Vertex","name":"openInterestDeviation End","project":"Superalgos","id":"b4b2a034-19f0-4069-bb3b-dedf524bb993","savedPayload":{"position":{"x":14979.403477329291,"y":16758.441271000705},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation End","id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2"}}}],"id":"b38a785b-70da-4d5c-bf56-064fcc5d55b8","savedPayload":{"position":{"x":14391.254512495416,"y":18043.757272775856},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"bullPriceDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 3,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"345cc144-aed2-4aaf-9e5d-8a9e628704a2","savedPayload":{"position":{"x":14936.030764208717,"y":16280.656443637166},"targetPosition":{"x":14838.360317871571,"y":16564.312016316962},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f0e9511b-24df-4a07-90df-78bed13778e0","savedPayload":{"position":{"x":14838.360317871571,"y":16564.312016316962},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"bullPriceDeviation Begin","project":"Superalgos","id":"6c8f60ee-9ee0-4a0f-bf00-1519a8ba31ec","savedPayload":{"position":{"x":15010.328085424175,"y":16716.456244960038},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation Begin","id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf"}}},{"type":"Polygon Vertex","name":"bullPriceDeviation End","project":"Superalgos","id":"31202df8-551d-48cb-87ee-a782dc2fd278","savedPayload":{"position":{"x":15024.34544421422,"y":16945.63803533391},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation End","id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f"}}}],"id":"137e3254-785f-4469-84f6-b654b34fe6b5","savedPayload":{"position":{"x":14364.288439178888,"y":18144.39602847377},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"33e571bd-9a26-4e88-8427-5b863d0aed70","savedPayload":{"position":{"x":14092.396103067893,"y":18017.610549951558},"targetPosition":{"x":13880.26406871193,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"13acaaae-6a8e-4e48-a326-9d209079629f","savedPayload":{"position":{"x":13880.26406871193,"y":18229.74258430752},"targetPosition":{"x":13668.132034355966,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3548ecec-25e1-4bb8-86c5-9743052bd80b","savedPayload":{"position":{"x":13668.132034355966,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b4f0c498-27c5-4c28-acef-67ff7f317e38","savedPayload":{"position":{"x":13456.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}} \ No newline at end of file From e01ff6b78f778648815737de2aac32e378ec3326 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:14:04 +0200 Subject: [PATCH 16/32] Omega One Data Mine docs --- ...-one-data-mine-002-chaikin-oscillator.json | 15 ++++++++ ...one-data-mine-003-arps-slow-arps-fast.json | 35 +++++++++++++++++++ ...-one-data-mine-004-average-vs-average.json | 19 ++++++++-- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json index 75afc7464..fccd1c0d8 100644 --- a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-002-chaikin-oscillator.json @@ -65,6 +65,21 @@ "style": "Text", "text": "A positive divergence signals a stock price is likely to rise, given the increase in accumulation. A negative divergence signals a stock price is likely to fall, given the increase in distribution." }, + { + "style": "Subtitle", + "text": "Products, Properties & Examples", + "updated": 1617967853007 + }, + { + "style": "Table", + "text": "| Product Name | Product Variable | Properties |\n| Chaikin Oscillator | chaikinOscillator | chaikinOscillator, zeroLine |", + "updated": 1617967606206 + }, + { + "style": "Javascript", + "text": "/* EXAMPLES */\n\n// Bullish cross\nchart.at01hs.chaikinOscillator.previous.chaikinOscillator < \nchart.at01hs.chaikinOscillator.previous.zeroLine && \nchart.at01hs.chaikinOscillator.chaikinOscillator > \nchart.at01hs.chaikinOscillator.zeroLine\n\n// Bearish cross\nchart.at01hs.chaikinOscillator.previous.chaikinOscillator > \nchart.at01hs.chaikinOscillator.previous.zeroLine && \nchart.at01hs.chaikinOscillator.chaikinOscillator < \nchart.at01hs.chaikinOscillator.zeroLine", + "updated": 1617967996718 + }, { "style": "Subtitle", "text": "" diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json index a68767c99..b05156a0a 100644 --- a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-003-arps-slow-arps-fast.json @@ -123,6 +123,41 @@ "text": "PNGs/Superalgos/Docs/indicators/arps-user-defined.png", "updated": 1617954568478 }, + { + "style": "Subtitle", + "text": "Products, Properties & Examples", + "updated": 1617967853007 + }, + { + "style": "Table", + "text": "| Product Name | Product Variable | Properties |\n| ARPS Slow | slowARPS | ARPS, apsBull, apsBear, SMA, percentageARPS, percentageApsBull, percentage apsBear |", + "updated": 1617968683265 + }, + { + "style": "Javascript", + "text": "/* EXAMPLES for ARPS Slow */\n\n// Bullish cross (Bull Power turns greater than Bear Power)\nchart.at01hs.slowARPS.previous.apsBull < \nchart.at01hs.slowARPS.previous.apsBear && \nchart.at01hs.slowARPS.apsBull > \nchart.at01hs.slowARPS.apsBear\n\n// Bearish cross (Bear Power turns greater than Bull Power)\nchart.at01hs.slowARPS.previous.apsBull > \nchart.at01hs.slowARPS.previous.apsBear && \nchart.at01hs.slowARPS.apsBull < \nchart.at01hs.slowARPS.apsBear\n\n// Average Price is going up compared to previous Average Price\nchart.at01hs.slowARPS.previous.SMA < chart.at01hs.slowARPS.SMA\n\n// The Average Range, measured in percent, is greater than 0.5%\nchart.at01hs.slowARPS.percentageARPS > 0.5\n\n// The Average Range, measured in rate, is greater than 1\nchart.at01hs.slowARPS.ARPS > 1", + "updated": 1617969217661 + }, + { + "style": "Table", + "text": "| Product Name | Product Variable | Properties |\n| ARPS Fast | fastARPS | ARPS, apsBull, apsBear, SMA, percentageARPS, percentageApsBull, percentage apsBear |", + "updated": 1617969400921 + }, + { + "style": "Javascript", + "text": "/* EXAMPLES for ARPS Fast */\n\n// Bullish cross (Bull Power turns greater than Bear Power)\nchart.at01hs.fastARPS.previous.apsBull < \nchart.at01hs.fastARPS.previous.apsBear && \nchart.at01hs.fastARPS.apsBull > \nchart.at01hs.fastARPS.apsBear\n\n// Bearish cross (Bear Power turns greater than Bull Power)\nchart.at01hs.fastARPS.previous.apsBull > \nchart.at01hs.fastARPS.previous.apsBear && \nchart.at01hs.fastARPS.apsBull < \nchart.at01hs.fastARPS.apsBear\n\n// Average Price is going up compared to previous Average Price\nchart.at01hs.fastARPS.previous.SMA < chart.at01hs.slowARPS.SMA\n\n// The Average Range, measured in percent, is greater than 0.5%\nchart.at01hs.fastARPS.percentageARPS > 0.5\n\n// The Average Range, measured in rate, is greater than 1\nchart.at01hs.fastARPS.ARPS > 1", + "updated": 1617969438749 + }, + { + "style": "Subtitle", + "text": "That Wombo-Combo!", + "updated": 1617969861080 + }, + { + "style": "Javascript", + "text": "/* EXAMPLES for ARPS Slow and ARPS Fast combined */\n\n// Fast SMA crosses Slow SMA (Bullish)\nchart.at01hs.fastARPS.previous.SMA < \nchart.at01hs.slowARPS.previous.SMA && \nchart.at01hs.fastARPS.SMA > \nchart.at01hs.slowARPS.SMA\n\n// Fast Bull crosses Slow SMA (Bearish)\nchart.at01hs.fastARPS.previous.apsBull > \nchart.at01hs.slowARPS.previous.SMA && \nchart.at01hs.fastARPS.apsBull < \nchart.at01hs.slowARPS.SMA\n\n// Fast Average Price is above Slow Average Price\nchart.at01hs.fastARPS.SMA > chart.at01hs.slowARPS.SMA\n\n// The Fast Average Range is greater than 0.5 & greater than the Slow Average Range\nchart.at01hs.fastARPS.percentageARPS > 0.5 &&\nchart.at01hs.fastARPS.ARPS > chart.at01hs.slowARPS.ARPS", + "updated": 1617969959288 + }, { "style": "Subtitle", "text": "" diff --git a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json index 1a7a36dff..d46540ede 100644 --- a/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json +++ b/Projects/Superalgos/Schemas/Docs-Topics/omega-one-data-mine-004-average-vs-average.json @@ -39,8 +39,8 @@ }, { "style": "List", - "text": "A zero-line that represents the slow average of the elements.", - "updated": 1617960380897 + "text": "A mid-line that represents the slow average of the elements (it always has the value 1).", + "updated": 1617973206308 }, { "style": "List", @@ -165,6 +165,21 @@ "text": "PNGs/Superalgos/Docs/indicators/average-vs-average-user-defined.png", "updated": 1617958965558 }, + { + "style": "Subtitle", + "text": "Products, Properties & Examples", + "updated": 1617967853007 + }, + { + "style": "Table", + "text": "| Product Name | Product Variable | Properties |\n| Average VS Average | averageVsAverage | bullPriceDeviation, smaPrice, volumeDeviation, openInterestDeviation |", + "updated": 1617972838194 + }, + { + "style": "Javascript", + "text": "/* EXAMPLES */\n\n// Average price is increasing compared to the slow average price\nchart.at01hs.averageVsAverage.previous.smaPrice < \nchart.at01hs.averageVsAverage.smaPrice\n\n// Bull Power crosses the mid-line (mid-line is always '1') (Bullish)\nchart.at01hs.averageVsAverage.previous.bullPriceDeviation < 1 &&\nchart.at01hs.averageVsAverage.bullPriceDeviation > 1\n\n// Bull Power crosses the mid-line while Open Interest is above mid-line (Bullish)\n( chart.at01hs.averageVsAverage.previous.bullPriceDeviation < 1 &&\nchart.at01hs.averageVsAverage.bullPriceDeviation > 1 ) &&\nchart.at01hs.averageVsAverage.openInterestDeviation < 1\n\n// Volume increases and SMA Price is below mid-line and SMA Price is getting stronger\nchart.at01hs.averageVsAverage.previous.volumeDeviation < \nchart.at01hs.averageVsAverage.volumeDeviation &&\nchart.at01hs.averageVsAverage.smaPrice < 1 &&\nchart.at01hs.averageVsAverage.previous.smaPrice < \nchart.at01hs.averageVsAverage.smaPrice", + "updated": 1617973639173 + }, { "style": "Text", "text": "" From 89f07ef6495c37e0f0498d4ac5d2a797653edab5 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:25:26 +0200 Subject: [PATCH 17/32] New name "Omega One" --- Projects/Superalgos/Plugins/Data-Mines/Omega.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Projects/Superalgos/Plugins/Data-Mines/Omega.json diff --git a/Projects/Superalgos/Plugins/Data-Mines/Omega.json b/Projects/Superalgos/Plugins/Data-Mines/Omega.json deleted file mode 100644 index 0ce7c2d8e..000000000 --- a/Projects/Superalgos/Plugins/Data-Mines/Omega.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"Data Mine","name":"Omega","config":"{\n \"codeName\": \"Omega\"\n}","project":"Superalgos","sensorBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Fast","project":"Superalgos","id":"d3431f91-842e-459b-b969-e93269ab06ee","savedPayload":{"position":{"x":17451.72948123781,"y":40729.60591487127},"targetPosition":{"x":17509.963766385878,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"5132afea-630c-455f-be7c-8d94469a239d"}}}],"outputDatasetFolders":[],"id":"81ac5c2c-7766-44ed-8e84-94b42ffbf7ab","savedPayload":{"position":{"x":17509.963766385878,"y":40946.93922578631},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"dc491dd3-55ba-40ac-8f8e-0dd6d8e8e877","savedPayload":{"position":{"x":17570.18233668201,"y":40849.511367860556},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"5a92a4fb-51ab-4ac6-9e6c-834767b542b4"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"95097e44-2b3c-4368-84ad-73f5d6ca1d89","savedPayload":{"position":{"x":17655.549479256046,"y":40838.27257032879},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"0538007e-1eb0-4208-b848-4f7ff62588fa","savedPayload":{"position":{"x":17723.86019460776,"y":40890.68922578631},"targetPosition":{"x":17626.43233668201,"y":40946.93922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"84ef19f0-4c0b-4cec-844c-e4b7b1758f64","savedPayload":{"position":{"x":17626.43233668201,"y":40946.93922578631},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"5a92a4fb-51ab-4ac6-9e6c-834767b542b4","savedPayload":{"position":{"x":17886.39610306789,"y":40846.0744851674},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"301b012f-4e33-4549-89c3-90bf2f992458","savedPayload":{"position":{"x":17785.531362448986,"y":41106.038251553284},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"e226b09c-b34e-493e-a9cb-c6562faa8ad2","savedPayload":{"position":{"x":17785.531362448986,"y":41222.50682184941},"targetPosition":{"x":17568.198051533946,"y":41164.27253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0c56f6f-d2dd-4d09-bd32-98e75221d015","savedPayload":{"position":{"x":15187.198051533946,"y":41176.27253670135},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Fast","project":"Superalgos","id":"c2993196-c4fb-4804-99b7-bf15c2f9e899","savedPayload":{"position":{"x":18150,"y":40703.047724829295},"targetPosition":{"x":17925,"y":41092.759156532295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"82f018e1-8fbd-4f93-b708-7bced5b23671"}}}],"outputDatasetFolders":[],"id":"d19d52df-3197-47d4-9f1d-c58b6fda2a87","savedPayload":{"position":{"x":17925,"y":41092.759156532295},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"60ec7290-4564-4609-93f2-046e7adefd51","savedPayload":{"position":{"x":18334.79899745976,"y":40880.068832659854},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"46093d66-daaa-4f01-b9e8-2c8001878a4e"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"0f7886f9-2cb3-403a-a71a-0620123d69e4","savedPayload":{"position":{"x":18439.427114358634,"y":40974.276412262865},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"fca6d255-88bf-43e1-947c-8b52cf9c8410","savedPayload":{"position":{"x":18509.822623626736,"y":41096.20501093991},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"5555532e-03cc-4eb3-a922-b175291abe9c","savedPayload":{"position":{"x":18539.094722342554,"y":41233.91940792597},"targetPosition":{"x":18089.711431703,"y":41257.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"2eb87964-42f6-472f-9f82-ae7ce3cc175b","savedPayload":{"position":{"x":18089.711431703,"y":41257.470588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"46093d66-daaa-4f01-b9e8-2c8001878a4e","savedPayload":{"position":{"x":18150,"y":41482.470588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"df3b3c25-507f-43b2-b620-c1163cdbbf99","savedPayload":{"position":{"x":17894.8557158515,"y":41594.970588235294},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"63452d0d-1cf4-4bc8-9f8e-e42ddc4da4c7","savedPayload":{"position":{"x":17812.5,"y":41677.32630408679},"targetPosition":{"x":17700,"y":41482.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e83d3882-522d-47ee-a853-9fd48c52a962","savedPayload":{"position":{"x":15319,"y":41494.470588235294},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Fast","config":"{\n \"codeName\": \"fastARPS\",\n \"singularVariableName\": \"fastARPS\",\n \"pluralVariableName\": \"fastARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"5132afea-630c-455f-be7c-8d94469a239d","savedPayload":{"position":{"x":15377.438536534504,"y":41659.67228307919},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"82f018e1-8fbd-4f93-b708-7bced5b23671","savedPayload":{"position":{"x":15348.433991612474,"y":41842.79977251312},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"6256f160-7706-4ff2-ae9a-3cd8d266fddf","savedPayload":{"position":{"x":18327.13933855677,"y":42135.34585808014},"targetPosition":{"x":18030.832836378235,"y":42182.276197592204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"333362de-b155-4287-90ca-f1d19e5de3ca","savedPayload":{"position":{"x":18030.832836378235,"y":42182.276197592204},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"c28a92c4-3eb2-41d2-8e27-61293dad8ed8","savedPayload":{"position":{"x":18327.13933855677,"y":42323.06721612842},"targetPosition":{"x":18030.832836378235,"y":42276.13687661635},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b695741-ce14-4efb-af70-61fe74d65089","savedPayload":{"position":{"x":18030.832836378235,"y":42276.13687661635},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"fb21f59f-0eec-4b84-940c-c4eb222e75d9","savedPayload":{"position":{"x":18135.479270084455,"y":42433.50226198707},"targetPosition":{"x":18001.8282914562,"y":42365.40368702614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"8b4fd778-668a-4e84-84f0-c3ef86143c97","savedPayload":{"position":{"x":18001.8282914562,"y":42365.40368702614},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"f044a4b5-54d6-4fec-a35f-a384a6a8b601","savedPayload":{"position":{"x":18052.724385733636,"y":42547.40458863822},"targetPosition":{"x":17946.658368555654,"y":42441.33857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9f7c4c1a-1062-49e5-a37c-d8cff8b4de15","savedPayload":{"position":{"x":17946.658368555654,"y":42441.33857146024},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"7835dee1-825c-4467-8cf6-180ab71f04f2","savedPayload":{"position":{"x":17938.822059082486,"y":42630.15947298904},"targetPosition":{"x":17870.723484121554,"y":42496.50849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"10554c37-8b71-46a7-a58c-fa70b517a45d","savedPayload":{"position":{"x":17870.723484121554,"y":42496.50849436079},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"0cbfa484-337e-47eb-98b3-209a5683e3d4","savedPayload":{"position":{"x":17804.921843467797,"y":42673.666290372086},"targetPosition":{"x":17781.456673711764,"y":42525.513039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"cd7c2e47-4b7e-4cee-8967-820c040f8a4d","savedPayload":{"position":{"x":17781.456673711764,"y":42525.513039282814},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"01c1be70-508f-4533-af13-3654530e3eeb","savedPayload":{"position":{"x":17664.130824931588,"y":42673.666290372086},"targetPosition":{"x":17687.595994687625,"y":42525.513039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3c947876-5900-4552-8e95-aa0f77871389","savedPayload":{"position":{"x":17687.595994687625,"y":42525.513039282814},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"01086358-6fdd-462c-9a3b-89edca234dc1","savedPayload":{"position":{"x":17530.230609316895,"y":42630.15947298904},"targetPosition":{"x":17598.329184277827,"y":42496.50849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c2095ffb-e643-4a6c-91f0-ccf0e4f20982","savedPayload":{"position":{"x":17598.329184277827,"y":42496.50849436079},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"6ce6dd46-1296-4b13-afab-84d1823351b8","savedPayload":{"position":{"x":17416.328282665745,"y":42547.40458863822},"targetPosition":{"x":17522.394299843727,"y":42441.33857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7a6db1af-b519-4674-a850-10f9e64358ab","savedPayload":{"position":{"x":17522.394299843727,"y":42441.33857146024},"targetPosition":{"x":17734.52633419969,"y":42229.20653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"36353357-8bb9-44e2-80ae-19eec60b1516","savedPayload":{"position":{"x":15353.526334199692,"y":42241.20653710428},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"// Loop Code\n\nlet nCandles = 3 // Change here number of candles to use\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// End of Code :-)","project":"Superalgos","id":"ad10cba8-9086-4846-af86-00082eb86754","savedPayload":{"position":{"x":15060.333810660808,"y":42251.539598611875},"targetPosition":{"x":15049.880964334043,"y":42152.087409075044},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b749a547-69ea-47fb-837f-1190a5ec2ebd","savedPayload":{"position":{"x":15049.880964334043,"y":42152.087409075044},"targetPosition":{"x":15034.201694843894,"y":42002.9091247698},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"955d2caa-e4d0-4e19-bf62-1d48f44c5a69","savedPayload":{"position":{"x":14932.517534074945,"y":42231.295489180455},"targetPosition":{"x":14973.191198382525,"y":42139.94094341619},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b4cb1e91-d42e-4165-8598-73874f217df5","savedPayload":{"position":{"x":14973.191198382525,"y":42139.94094341619},"targetPosition":{"x":15034.201694843894,"y":42002.9091247698},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"32fc144f-fcf7-4e27-a4ce-9964a6240653","savedPayload":{"position":{"x":15034.201694843894,"y":42002.9091247698},"targetPosition":{"x":15081.132034355964,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"fe7a8b58-37c4-4e51-a037-6eedcd8e9dfb","savedPayload":{"position":{"x":15081.132034355964,"y":41706.60262259126},"targetPosition":{"x":14869,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS","id":"2675db9e-a697-4f84-a252-8c27ed423e24"}}}],"id":"892f3bfe-6b06-491b-994a-825c96bf0e72","savedPayload":{"position":{"x":14869,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Chaikin Oscillator Data Procedure","project":"Superalgos","id":"ba931d51-1350-4df7-a2d5-2eff15cf844a","savedPayload":{"position":{"x":15417.430428875681,"y":41180.299462731185},"targetPosition":{"x":15336.79764022799,"y":41390.35505869306},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"ec6522f5-9165-4607-87a6-ea63e2f4d20e"}}}],"outputDatasetFolders":[],"id":"28505aa2-26a8-479c-bba7-782ed4066ca0","savedPayload":{"position":{"x":15336.79764022799,"y":41390.35505869306},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"ad424254-a304-41bb-9ba9-b8267455e0d2","savedPayload":{"position":{"x":15697.396278927989,"y":41111.66875071292},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"72244463-734d-4495-9eab-9ed63818963d"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"ee83aebb-ffed-415b-91c1-0f6fa3f79dfd","savedPayload":{"position":{"x":15756.434920666677,"y":41150.008892950085},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"2d08d62e-f0a9-45b4-b148-6fe217fdf5c6","savedPayload":{"position":{"x":15800.736250087433,"y":41204.7164786825},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"9b1e61f2-fd52-4ee2-9c57-ede4bbe084de","savedPayload":{"position":{"x":15825.96374440104,"y":41270.436348248506},"targetPosition":{"x":15605.880534235934,"y":41317.2164786825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"775e3d6e-71ed-4b61-a632-a80aefddbd49","savedPayload":{"position":{"x":15605.880534235934,"y":41317.2164786825},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"72244463-734d-4495-9eab-9ed63818963d","savedPayload":{"position":{"x":15700.62460484811,"y":41530.015145386824},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"11d0bcf4-9c53-428c-9fff-feb3f72c4ad1","savedPayload":{"position":{"x":15466.220447542168,"y":41681.043443302624},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"ff07193a-4761-45da-a5b0-d4a0f65d5dbb","savedPayload":{"position":{"x":15397.76193956651,"y":41775.268495982746},"targetPosition":{"x":15256.164851580297,"y":41600.41065465493},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7abd43da-a0dc-477c-b6eb-9e63b21e5262","savedPayload":{"position":{"x":15256.164851580297,"y":41600.41065465493},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Chaikin Oscillator Data Procedure","project":"Superalgos","id":"d3a96bb9-4c2d-4bbd-ada0-1c8bb456fffe","savedPayload":{"position":{"x":15997.953657659551,"y":41569.246548686424},"targetPosition":{"x":15586.85820172038,"y":41752.27803807054},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"bcb93023-ae74-48f0-a26b-2f2d57c57740"}}}],"outputDatasetFolders":[],"id":"4858b9f4-4354-4e9a-9581-da02aa2619e1","savedPayload":{"position":{"x":15586.85820172038,"y":41752.27803807054},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Daily","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"973153da-c1d7-4643-a367-21c40ce30ebd","savedPayload":{"position":{"x":16034.393054636104,"y":41799.31584654098},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"4a5ee296-a995-48fe-b8ac-1b7e54cbdcdd"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"8327acb7-ef19-4e57-b44d-2871da44d621","savedPayload":{"position":{"x":16067.757351964747,"y":41911.95182665699},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{\n \"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"209f3ffc-3c8b-4e5f-91ce-80e8c5f41bf1","savedPayload":{"position":{"x":16070.832451612658,"y":42029.385144395535},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"93f3541a-f954-4980-bcc8-4e0ae868f5ca","savedPayload":{"position":{"x":16043.408790620675,"y":42143.61291322048},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"65ae3b73-5a3e-411e-ac6c-332f0f8a36a1","savedPayload":{"position":{"x":15987.35524616566,"y":42246.85069945671},"targetPosition":{"x":15623.297598696934,"y":41982.34733592509},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"927e58b1-c870-45e0-b256-eb3fb22d9302","savedPayload":{"position":{"x":15623.297598696934,"y":41982.34733592509},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"4a5ee296-a995-48fe-b8ac-1b7e54cbdcdd","savedPayload":{"position":{"x":15539.820393249936,"y":42199.812890986264},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"5f26534d-432d-4be2-9aa8-0aa452dc95c6","savedPayload":{"position":{"x":15267.278490473265,"y":42140.857255424235},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"11ee3e01-af54-40ed-b3ac-fde2d322cd7e","savedPayload":{"position":{"x":15152.24384154599,"y":42159.07695391251},"targetPosition":{"x":15175.76274578121,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e60b83a0-fb61-4bf2-87dc-9a3c444153b9","savedPayload":{"position":{"x":15175.76274578121,"y":41935.30952745465},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Chaikin Oscillator Data Procedure","config":"{\n \"codeName\": \"ChaikinOscillator\",\n \"singularVariableName\": \"ChaikinOscillator\",\n \"pluralVariableName\": \"ChaikinOscillators\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"ec6522f5-9165-4607-87a6-ea63e2f4d20e","savedPayload":{"position":{"x":15125.937395081064,"y":42103.309816023444},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"bcb93023-ae74-48f0-a26b-2f2d57c57740","savedPayload":{"position":{"x":14994.832587746418,"y":42234.41462335809},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"59d6bee5-111c-4309-8070-ebe49c60285a","savedPayload":{"position":{"x":15231.062335674598,"y":42937.31790508857},"targetPosition":{"x":14997.918547237507,"y":42748.521787773614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"4a56532a-32af-4c09-861a-7b0ec19aa90f","savedPayload":{"position":{"x":14997.918547237507,"y":42748.521787773614},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"cac1f7d5-bba0-487e-8a88-96d241085815","savedPayload":{"position":{"x":14979.795528527595,"y":43119.87392635699},"targetPosition":{"x":14872.285143664005,"y":42839.799798407825},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0d2e4662-fbdf-490b-8553-b069cf732f62","savedPayload":{"position":{"x":14872.285143664005,"y":42839.799798407825},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if ( isNaN(variable.chaikinOscillator ) )\n{ variable.chaikinOscillator = 0 }\nelse\n{ variable.chaikinOscillator }","project":"Superalgos","id":"c0570b4b-c935-4511-80a0-965874de3aab","savedPayload":{"position":{"x":14694.37924953231,"y":43004.18542372648},"targetPosition":{"x":14717.844419288345,"y":42856.032172637206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f07b74fd-4beb-409b-99e1-ed51c746bc63","savedPayload":{"position":{"x":14717.844419288345,"y":42856.032172637206},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Zero Line","config":"{\n \"codeName\": \"zeroLine\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"0","project":"Superalgos","id":"c37d5f0d-81f7-46bc-9693-9d854f2d4190","savedPayload":{"position":{"x":14481.580582827988,"y":42909.4413531143},"targetPosition":{"x":14575.978641485464,"y":42792.86945889575},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b5d9bc2b-386e-4670-abee-e828107a5015","savedPayload":{"position":{"x":14575.978641485464,"y":42792.86945889575},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"ADL","config":"{\n \"codeName\": \"ADL\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.accDistLine))\n{ variable.accDistLind = 0 }\nelse\n{ variable.accDistLine }","project":"Superalgos","id":"f617da69-165b-4875-88d6-0edfa8769d2f","savedPayload":{"position":{"x":14344.663566876674,"y":42720.99124775405},"targetPosition":{"x":14484.700630851254,"y":42667.23605532225},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c105d752-f310-4917-ac54-65ff02021576","savedPayload":{"position":{"x":14484.700630851254,"y":42667.23605532225},"targetPosition":{"x":14764.774758800415,"y":42559.72567045866},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e5529d72-8e8d-4a32-b700-13bdb3ab4dd0","savedPayload":{"position":{"x":14764.774758800415,"y":42559.72567045866},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Loop Code */\n\n/* Chaikin Oscillator\n\nKEY TAKEAWAYS\n- The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n- A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish.\n\n1. Money Flow Multiplier = [(Close - Low) - (High - Close)] / (High - Low) \n2. Money Flow Volume = Money Flow Multiplier x Volume for the Period\n3. ADL = Previous ADL + Current Period's Money Flow Volume\n4. Chaikin Oscillator = ('fast'-period EMA of ADL) - ('slow'-period EMA of ADL) */\n\n\nlet fastPeriod = 5 // Change value to set 'fast' period (must be less than or equal to 'fast')\nlet slowPeriod = 17 // Change value to set 'slow' period (must be greater than or equal to 'slow')\n\nlet candle = record.current\nlet volume = getElement('volumes', candle)\n\n\n// Set varibles\nvariable.totalVolume = volume.buy + volume.sell\t\nvariable.moneyFlowMultiplier = ((candle.close - candle.min) - (candle.max - candle.close)) / (candle.max - candle.min) \nvariable.moneyFlowVolume = variable.moneyFlowMultiplier * variable.totalVolume \nvariable.currentADL = variable.totalVolume + variable.moneyFlowVolume\nvariable.savedADL.push(variable.currentADL) // Push the currentADL into an array to be able to use \"previous ADL\"\n\nif (variable.savedADL.length > 2) { // Make sure we only save the current and previous\n variable.savedADL.splice(0, 1)\n}\n\n// Calculating the 'accDistLine' using previous ADL value if it is defined, else current\nif (variable.savedADL[0] === 'undefined')\n{variable.accDistLine = variable.savedADL[1] + variable.moneyFlowVolume} // Calculating with Current ADL\nelse\n{variable.accDistLine = variable.savedADL[0] + variable.moneyFlowVolume} // Calculating with Previous ADL\n\n\n// Calculate fastEMA and slowEMA of ADL\nif(isNaN(variable.previousEmaFast))\n{variable.previousEmaFast = variable.accDistLine}\nelse\n{variable.previousEmaFast}\n\nvariable.fastEMA = calculateEMAs(fastPeriod, variable.accDistLine, variable.previousEmaFast)\nvariable.previousEmaFast = variable.fastEMA\n\nif(isNaN(variable.previousEmaSlow))\n{variable.previousEmaSlow = variable.accDistLine}\nelse\n{variable.previousEmaSlow}\nvariable.slowEMA = calculateEMAs(slowPeriod, variable.accDistLine, variable.previousEmaSlow)\nvariable.previousEmaSlow = variable.slowEMA\n\n\n// Create EMA function for 'fast' and 'slow' ADL\nfunction calculateEMAs(periods, adl, previousEMA) {\n let k = 2 / (periods + 1)\n return adl * k + previousEMA * (1-k)\n}\n\n// Calculate Chaikin Oscillator value\nvariable.chaikinOscillator = variable.fastEMA - variable.slowEMA\n\n/*\n// Printing values to console to check\nconsole.log(\"Volume: \", variable.totalVolume)\nconsole.log(\"MF x: \", variable.moneyFlowMultiplier)\nconsole.log(\"MF Vol: \", variable.moneyFlowVolume)\nconsole.log(\"Current ADL: \", variable.currentADL)\nconsole.log(\"AccDistLine: \", variable.accDistLine)\nconsole.log(\"Fast EMA: \", variable.fastEMA)\nconsole.log(\"Slow EMA: \", variable.slowEMA)\nconsole.log(\"Chaikin Oscillator: \", variable.chaikinOscillator)\n*/","project":"Superalgos","id":"c0132fa6-7f08-4457-9656-05bba93d9cca","savedPayload":{"position":{"x":14521.50340346859,"y":42395.751051403655},"targetPosition":{"x":14571.50340346859,"y":42309.14851102521},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"01efe8a3-bfc2-43ee-b29e-a72c9fa7ab5f","savedPayload":{"position":{"x":14571.50340346859,"y":42309.14851102521},"targetPosition":{"x":14646.50340346859,"y":42179.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build arrays \n\nvariable.savedADL = []\n\n","project":"Superalgos","id":"6199432b-91d5-471d-b5e2-5cbbfeed340c","savedPayload":{"position":{"x":14429.99705252248,"y":42304.244700457544},"targetPosition":{"x":14516.599592900924,"y":42254.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2ea55eba-609e-4780-8333-7ca25058c8ab","savedPayload":{"position":{"x":14516.599592900924,"y":42254.244700457544},"targetPosition":{"x":14646.50340346859,"y":42179.244700457544},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"4be72b8f-5821-473b-9b38-26c665856101","savedPayload":{"position":{"x":14646.50340346859,"y":42179.244700457544},"targetPosition":{"x":14858.635437824554,"y":41967.11266610158},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"14ad8763-cbf9-43e0-8132-16be260a8d2c","savedPayload":{"position":{"x":14858.635437824554,"y":41967.11266610158},"targetPosition":{"x":14811.705098312485,"y":41670.80616392304},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Chaikin Oscillator","id":"653018cc-a18a-4370-a6c5-e0ad879b2c2f"}}}],"id":"627939de-3884-4de8-99a9-35d0e66fa2d4","savedPayload":{"position":{"x":14781.132034355964,"y":41706.60262259126},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Slow ARPS","project":"Superalgos","id":"03519cbc-2f6a-4ac2-9c28-e33e61384619","savedPayload":{"position":{"x":16874.72948123781,"y":41057.10591487127},"targetPosition":{"x":16932.963766385874,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"c7403fbf-2ca8-41b4-8e24-a5ec34818127"}}}],"outputDatasetFolders":[],"id":"27246891-a94e-4a4e-9cb1-b7487c876f47","savedPayload":{"position":{"x":16932.963766385874,"y":41274.43922578631},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"76089903-5360-4ee6-ae07-dcc91ed96482","savedPayload":{"position":{"x":16993.18233668201,"y":41177.011367860556},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2b630c1d-86e7-4144-be9e-b7ba0ae8ecf6"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"50b106cc-4d03-499e-a5a3-e1aa4cd8215c","savedPayload":{"position":{"x":17078.549479256042,"y":41165.77257032879},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"d9a2dab2-c16a-4d07-9978-77e9bf72f5d2","savedPayload":{"position":{"x":17146.86019460776,"y":41218.18922578631},"targetPosition":{"x":17049.43233668201,"y":41274.43922578631},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"90f657aa-0f1f-43c2-ab2d-c91a6cfba4b6","savedPayload":{"position":{"x":17049.43233668201,"y":41274.43922578631},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"2b630c1d-86e7-4144-be9e-b7ba0ae8ecf6","savedPayload":{"position":{"x":17309.39610306789,"y":41173.5744851674},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"087388b9-9acb-40ac-b76e-23bf36e35f05","savedPayload":{"position":{"x":17208.531362448986,"y":41433.538251553284},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"57d2e4a3-6ed0-4b57-a107-39438f91b0e9","savedPayload":{"position":{"x":17208.531362448986,"y":41550.00682184941},"targetPosition":{"x":16991.198051533946,"y":41491.77253670135},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c4f909d9-665a-41ee-9dce-d8e75ea7a43f","savedPayload":{"position":{"x":14356.867965644036,"y":42156.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Slow ARPS","project":"Superalgos","id":"45e34e9d-ef1b-4273-a805-def2f0d4092f","savedPayload":{"position":{"x":17573,"y":41030.547724829295},"targetPosition":{"x":17348,"y":41420.259156532295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"4bff21d4-3de0-4e8e-9f63-b7792996247d"}}}],"outputDatasetFolders":[],"id":"d47a3468-9012-45ea-8c97-317d574f239b","savedPayload":{"position":{"x":17348,"y":41420.259156532295},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"0ce21a09-c93a-499b-8367-f9abf9192022","savedPayload":{"position":{"x":17757.79899745976,"y":41207.568832659854},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a4e156b7-d673-49b0-81bf-6d3d503abd34"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"09887b9d-20ed-4069-b794-d0ad12ec4847","savedPayload":{"position":{"x":17862.42711435863,"y":41301.776412262865},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"febb0ddf-d6b6-4930-9620-58e0033a3e14","savedPayload":{"position":{"x":17932.822623626736,"y":41423.70501093991},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"a9bcd7f0-525e-4eea-a2ad-0e6f987e5799","savedPayload":{"position":{"x":17962.094722342554,"y":41561.41940792597},"targetPosition":{"x":17512.711431703,"y":41584.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"d237a234-82ae-473d-9659-0433797141b0","savedPayload":{"position":{"x":17512.711431703,"y":41584.970588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"a4e156b7-d673-49b0-81bf-6d3d503abd34","savedPayload":{"position":{"x":17573,"y":41809.970588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"c02c96bc-833b-4463-b774-a6753f47278c","savedPayload":{"position":{"x":17317.855715851496,"y":41922.470588235294},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"9087ca64-0068-4292-8d22-9228c58f34c5","savedPayload":{"position":{"x":17235.5,"y":42004.82630408679},"targetPosition":{"x":17123,"y":41809.970588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"6d1b63a8-1ea2-47f3-8349-499c63f39446","savedPayload":{"position":{"x":14038.66991411009,"y":42024.8006741252},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Slow ARPS","config":"{\n \"codeName\": \"slowARPS\",\n \"singularVariableName\": \"slowARPS\",\n \"pluralVariableName\": \"slowARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"c7403fbf-2ca8-41b4-8e24-a5ec34818127","savedPayload":{"position":{"x":13880.532389956294,"y":41949.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"4bff21d4-3de0-4e8e-9f63-b7792996247d","savedPayload":{"position":{"x":13771.551010755491,"y":41799.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"1ab4b7a0-7c36-4ab7-8db3-1485543531b2","savedPayload":{"position":{"x":17750.13933855677,"y":42462.84585808014},"targetPosition":{"x":17453.832836378235,"y":42509.776197592204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"26848c50-95de-4b02-bc64-38b35ba53578","savedPayload":{"position":{"x":17453.832836378235,"y":42509.776197592204},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"a2f026df-7bfd-46a9-937e-2ebcf911b373","savedPayload":{"position":{"x":17750.13933855677,"y":42650.56721612842},"targetPosition":{"x":17453.832836378235,"y":42603.63687661635},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b80933e3-e479-4d3c-a4ee-c5f81266839e","savedPayload":{"position":{"x":17453.832836378235,"y":42603.63687661635},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"9a85c68f-55f6-4400-b541-e6fbef799189","savedPayload":{"position":{"x":17558.479270084455,"y":42761.00226198707},"targetPosition":{"x":17424.8282914562,"y":42692.90368702614},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"864fb9fd-074e-47ff-8b46-741e984babad","savedPayload":{"position":{"x":17424.8282914562,"y":42692.90368702614},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"6ebf0e39-e7e9-41d2-9419-58dd5037f95f","savedPayload":{"position":{"x":17475.724385733636,"y":42874.90458863822},"targetPosition":{"x":17369.658368555654,"y":42768.83857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"08b55166-37ee-4088-9878-8b8954315cee","savedPayload":{"position":{"x":17369.658368555654,"y":42768.83857146024},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"9b6e5a56-c971-42c5-9eda-919e82fc653b","savedPayload":{"position":{"x":17361.822059082486,"y":42957.65947298904},"targetPosition":{"x":17293.723484121554,"y":42824.00849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2d5b640c-0bf8-4170-a216-d1a75e321225","savedPayload":{"position":{"x":17293.723484121554,"y":42824.00849436079},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"c4b17d80-7441-482b-b920-89d68f56553e","savedPayload":{"position":{"x":17227.921843467797,"y":43001.166290372086},"targetPosition":{"x":17204.456673711764,"y":42853.013039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7833873a-bac5-4646-87e8-c8c2ae5409a2","savedPayload":{"position":{"x":17204.456673711764,"y":42853.013039282814},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"681f8933-bb6c-4311-92ff-215eb5a37f33","savedPayload":{"position":{"x":17087.130824931584,"y":43001.166290372086},"targetPosition":{"x":17110.595994687625,"y":42853.013039282814},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9dcd16cf-c609-43b7-896f-3f5d7209ae7e","savedPayload":{"position":{"x":17110.595994687625,"y":42853.013039282814},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"ab02063d-1b37-4024-b0fa-ee38859a6b50","savedPayload":{"position":{"x":16953.230609316895,"y":42957.65947298904},"targetPosition":{"x":17021.329184277827,"y":42824.00849436079},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2f44af53-9e90-4943-989c-54b2520c65aa","savedPayload":{"position":{"x":17021.329184277827,"y":42824.00849436079},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"c20bbde5-2d5b-4a30-9c6e-f98155159f5d","savedPayload":{"position":{"x":16839.328282665745,"y":42874.90458863822},"targetPosition":{"x":16945.394299843727,"y":42768.83857146024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"93555a22-0783-448a-be65-e529d4f8e685","savedPayload":{"position":{"x":16945.394299843727,"y":42768.83857146024},"targetPosition":{"x":17157.52633419969,"y":42556.70653710428},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ee9dcc1e-1f97-417a-bc3a-03ed97bf942b","savedPayload":{"position":{"x":13486.234055866944,"y":41521.19242596629},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"// Loop Code\n\nlet nCandles = 17 // Change here number of candles to use\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// End of Code :-)","project":"Superalgos","id":"966b7e24-c167-459d-8975-5a7b4e6b8d5e","savedPayload":{"position":{"x":13686.245899592052,"y":41306.56742651631},"targetPosition":{"x":13763.960495737749,"y":41369.499465621295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c17982f3-0168-48b9-90ac-b7bef7cdaa07","savedPayload":{"position":{"x":13763.960495737749,"y":41369.499465621295},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"b324a567-8972-40c1-9e4b-ece388320ef1","savedPayload":{"position":{"x":13790.940402569968,"y":41230.50241765447},"targetPosition":{"x":13826.777197524498,"y":41323.86046030419},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ce407fea-a38d-4b44-abb5-2195ffc010e3","savedPayload":{"position":{"x":13826.777197524498,"y":41323.86046030419},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ba9e95be-ac7a-43ca-8709-08a562dce5be","savedPayload":{"position":{"x":13880.532389956294,"y":41463.89752427877},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"d56a976b-05eb-4aa5-9608-d8839690052c","savedPayload":{"position":{"x":14056.867965644036,"y":41706.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Slow","id":"ba1f7fe7-29a3-4cf2-b185-dc2c65e5cc5a"}}}],"id":"66aba56e-6265-4de6-baa9-eaea3f5fd8b8","savedPayload":{"position":{"x":14569,"y":41794.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market averageVsAverage","project":"Superalgos","id":"ff8f0062-8f35-45b5-9640-7998961fa0b8","savedPayload":{"position":{"x":14605.61507507505,"y":42398.460093163274},"targetPosition":{"x":14430.75723374723,"y":42256.86300517706},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2fa9132f-8809-4ab6-a7d3-21769b765195"}}}],"outputDatasetFolders":[],"id":"97c82560-d099-42c7-8d64-b8dc57e522ec","savedPayload":{"position":{"x":14430.75723374723,"y":42256.86300517706},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"70ebbcf2-3a50-4b5d-b857-a1bd35617a0b","savedPayload":{"position":{"x":14445.198836524623,"y":42354.43865572675},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"27ca72af-be47-4d79-9b0c-dadda0003dd2"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"964c9245-0231-4904-8625-db801ad1fa00","savedPayload":{"position":{"x":14407.33072506021,"y":42412.750433816625},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"445b8c4a-cfcf-4e00-b334-8eba9c4ce149","savedPayload":{"position":{"x":14342.419976144434,"y":42437.667335812606},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"1bc1b344-3f7d-48b7-950c-c85db9d23d2d","savedPayload":{"position":{"x":14275.260289627913,"y":42419.67195204658},"targetPosition":{"x":14336.532181067103,"y":42325.32151315272},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"38f8eb3e-5d3b-43c4-b303-d9d63e2b75b9","savedPayload":{"position":{"x":14336.532181067103,"y":42325.32151315272},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"27ca72af-be47-4d79-9b0c-dadda0003dd2","savedPayload":{"position":{"x":14185.503883151307,"y":42559.725670458654},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"0f18ef7c-8f85-43f3-81dd-d942b1317690","savedPayload":{"position":{"x":14114.302304433199,"y":42290.12375851866},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"7bc96372-69d4-4b2a-9a50-3aa19a47bb65","savedPayload":{"position":{"x":14045.84379645754,"y":42195.89870583854},"targetPosition":{"x":14255.899392419411,"y":42115.265917190845},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ae0de8e8-9ccc-480f-938c-cb05d8cba570","savedPayload":{"position":{"x":14356.867965644036,"y":42156.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily averageVsAverage","project":"Superalgos","id":"624d6b5e-41d4-4bd9-a445-21dd56645dc3","savedPayload":{"position":{"x":14056.312871159678,"y":42830.37923328609},"targetPosition":{"x":14009.275062689234,"y":42382.84438037037},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"144e811d-ea2c-41d9-9c5b-68f6ba800157"}}}],"outputDatasetFolders":[],"id":"6255fc01-a43a-4ac9-9e81-1013d85c6b12","savedPayload":{"position":{"x":14009.275062689234,"y":42382.84438037037},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"f0e71f8c-1f06-426d-8cc5-35a631c8e096","savedPayload":{"position":{"x":13826.243573305124,"y":42793.93983630954},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"f11c0a9b-276d-4e7c-8369-784bea139ced"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"207c7107-7169-4143-b9bc-627f1d4a92da","savedPayload":{"position":{"x":13708.810255566576,"y":42790.86473666163},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"e5d78941-5578-4385-a414-5273061e512a","savedPayload":{"position":{"x":13596.17427545057,"y":42757.50043933299},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"68f9c948-a066-447b-870a-86238da7c2ff","savedPayload":{"position":{"x":13496.011588862253,"y":42696.12066604946},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"56a9550b-8f7b-46b5-803f-f517209e23c2","savedPayload":{"position":{"x":13415.148117365954,"y":42610.90834692543},"targetPosition":{"x":13779.20576483468,"y":42346.40498339382},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"76ba561f-3ffb-48cf-9c10-bbe6387e1a0f","savedPayload":{"position":{"x":13779.20576483468,"y":42346.40498339382},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"f11c0a9b-276d-4e7c-8369-784bea139ced","savedPayload":{"position":{"x":13598.179606750064,"y":42199.812890986264},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"24742d14-280e-4f10-8602-bdd2862f4625","savedPayload":{"position":{"x":13738.469827760928,"y":41958.82843168987},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"716ce0a4-f43e-4f76-8101-20a577815d99","savedPayload":{"position":{"x":13756.689526249203,"y":41843.793782762594},"targetPosition":{"x":13962.23725421879,"y":41935.30952745465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0452a39-e3ec-4b20-bd70-0ebcb12c6246","savedPayload":{"position":{"x":14038.66991411009,"y":42024.8006741252},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"averageVsAverage","config":"{\n \"codeName\": \"averageVsAverage\",\n \"singularVariableName\": \"averageVsAverage\",\n \"pluralVariableName\": \"averageVsAverages\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"2fa9132f-8809-4ab6-a7d3-21769b765195","savedPayload":{"position":{"x":13880.532389956294,"y":41949.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"144e811d-ea2c-41d9-9c5b-68f6ba800157","savedPayload":{"position":{"x":13771.551010755491,"y":41799.307720903744},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"938c01c4-07de-4033-bdaa-17d8fb09d38a","savedPayload":{"position":{"x":12646.856347572095,"y":42200.0096619911},"targetPosition":{"x":13071.120416284024,"y":41775.74559327917},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"35c4d523-27c6-48c2-b2a1-2b4b63c2e84c","savedPayload":{"position":{"x":13071.120416284024,"y":41775.74559327917},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"e78d81f6-95be-4eee-a18e-5bfa7640c553","savedPayload":{"position":{"x":12426.176655969914,"y":41896.2701242547},"targetPosition":{"x":12960.780570482933,"y":41623.87582441097},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"05257927-f8b2-4a8b-a50e-a04c1efc3a3e","savedPayload":{"position":{"x":12960.780570482933,"y":41623.87582441097},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"fastPriceRange","config":"{\n \"codeName\": \"fastPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.fastPriceRange)) {\nvariable.fastPriceRange\n}\nelse {\nvariable.fastPriceRange = 1\n}","project":"Superalgos","id":"46081807-6648-45a7-a65a-16a9e8da966d","savedPayload":{"position":{"x":13050.924731728142,"y":41421.87703383534},"targetPosition":{"x":13199.077982817413,"y":41398.41186407931},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5307878c-aafa-410b-b43a-0bcd0020bb08","savedPayload":{"position":{"x":13199.077982817413,"y":41398.41186407931},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"slowPriceRange","config":"{\n \"codeName\": \"slowPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.slowPriceRange)) { \nvariable.slowPriceRange\n}\nelse { \nvariable.slowPriceRange = 1\n}","project":"Superalgos","id":"9e21a59a-9c44-47f3-be7f-5c03e8e945ef","savedPayload":{"position":{"x":13050.924731728142,"y":41281.086015299144},"targetPosition":{"x":13199.077982817413,"y":41304.55118505518},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"fdcb9976-a574-40be-bf72-1719da5dcd4e","savedPayload":{"position":{"x":13199.077982817413,"y":41304.55118505518},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"longTermPriceRange","config":"{\n \"codeName\": \"longTermPriceRange\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.longTermPriceRange)) {\nvariable.longTermPriceRange\n}\nelse {\nvariable.longTermPriceRange = 1\n}","project":"Superalgos","id":"2e627fae-2cb1-4f65-84a6-e77c6e88fa17","savedPayload":{"position":{"x":13094.431549111188,"y":41147.18579968445},"targetPosition":{"x":13228.082527739443,"y":41215.28437464538},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f8988c1b-4938-4a4a-b7f9-7d77d91ce534","savedPayload":{"position":{"x":13228.082527739443,"y":41215.28437464538},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"bullPriceDeviation","config":"{\n \"codeName\": \"bullPriceDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.bullPriceDeviation)) {\nvariable.bullPriceDeviation\n}\nelse {\nvariable.bullPriceDeviation = 1\n}","project":"Superalgos","id":"908c053b-f1eb-4ea4-b545-e954ffd3db1b","savedPayload":{"position":{"x":13177.186433462008,"y":41033.2834730333},"targetPosition":{"x":13283.25245063999,"y":41139.34949021128},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"37955412-117b-41ee-a43d-b803e46416d8","savedPayload":{"position":{"x":13283.25245063999,"y":41139.34949021128},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"smaPrice","config":"{\n \"codeName\": \"smaPrice\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.smaPrice)) {\nvariable.smaPrice\n}\nelse {\nvariable.smaPrice = 1\n}","project":"Superalgos","id":"8f6487d2-ef0b-42d9-b7a3-74045069fdad","savedPayload":{"position":{"x":13291.088760113158,"y":40950.52858868248},"targetPosition":{"x":13359.18733507409,"y":41084.17956731073},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c760cbf7-ea72-4716-aca7-f6a43d60a9af","savedPayload":{"position":{"x":13359.18733507409,"y":41084.17956731073},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"volumeDeviation","config":"{\n \"codeName\": \"volumeDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.volumeDeviation)) {\nvariable.volumeDeviation\n}\nelse {\nvariable.volumeDeviation = 1\n}","project":"Superalgos","id":"50217133-ddcd-4dd5-8c05-4c284eb3a164","savedPayload":{"position":{"x":13424.988975727849,"y":40907.02177129943},"targetPosition":{"x":13448.454145483884,"y":41055.1750223887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9d53e819-26a4-4e2d-999c-8c68a079a7ed","savedPayload":{"position":{"x":13448.454145483884,"y":41055.1750223887},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"openInterestDeviation","config":"{\n \"codeName\": \"openInterestDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.openInterestDeviation)) {\nvariable.openInterestDeviation\n}\nelse {\nvariable.openInterestDeviation = 1\n}","project":"Superalgos","id":"1a1bba7d-2ea4-452c-980a-885220669585","savedPayload":{"position":{"x":13565.779994264058,"y":40907.02177129943},"targetPosition":{"x":13542.314824508023,"y":41055.1750223887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"78f159de-c0d7-4373-93a1-645e6791fdfa","savedPayload":{"position":{"x":13542.314824508023,"y":41055.1750223887},"targetPosition":{"x":13495.384484995953,"y":41351.48152456724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"a1e299c4-fed7-4543-9d78-5697aef59e84","savedPayload":{"position":{"x":13486.234055866944,"y":41521.19242596629},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"EDIT TOP LINES HERE TO CHANGE PERIODS","code":"// The Average VS Average Oscillator\n\n/* The Average VS Average Oscillator can be used to recognize changes between a fast average ('fastPeriod') and a slow average ('slowPeriod'). It measures 'Price Action', 'Volume', and a so called 'Open Interest'.\n'Bull Price Action' and 'Bear Price Action' is defined by the amount between the candle close and max and min.\n'Bull Volume' and 'Bear Volume' is divided using the price action.\n'Open Interest' is based upon the statement where:\nBull Candle and Volume Increase = Bull Interest\nBull Candle and Volume Decrease = Bear Interest\nBear Candle and Volume Increase = Bear Interest\nBear Candle and Volume Decrease = Bull Interest */\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n/* Loop code */\n\n// User defined lengths of the used periods\n\nlet fastPeriod = 5 // Change this number to the period of your choice (must be less than 'slowPeriod')\nlet slowPeriod = 21 // Change this number to the period of your choice (must be greater than 'fastPeriod')\nlet periodMultiplier = 3 // The 'slowPeriod' is muliplied by the 'periodMultiplier to create the \"long term\" trend\nlet fastBoost = 1.00 // '1.00' equals 'no extra boost' to your 'fastPeriod' where as '1.23' would boost the value by 23%\nlet gravity = 0 // '0' equals 'no gravity' (pullback towards midline ('slowPeriod'))\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring variables used\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \nlet volCandle = record.current\nlet volume = getElement('volumes', volCandle)\nlet totalVolume = volume.buy + volume.sell\nlet totalRange = candle.max - candle.min\nlet multipliedFast = fastPeriod * periodMultiplier\nlet multipliedSlow = slowPeriod * periodMultiplier\n\nif ( candle.close > candle.open ) { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\nelse { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Volume Difference'\n\nvariable.previousCurrentVolume.push(totalVolume)\nif (variable.previousCurrentVolume.length > 2) {\n variable.previousCurrentVolume.splice(0, 1)\n}\n\nif (variable.previousCurrentVolume[1] === 'undefined') {\n variable.positiveVolumeDifference = 0.01\n}\nelse {\n if (variable.previousCurrentVolume[variable.previousCurrentVolume.max] > variable.previousCurrentVolume[0]) {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[1] - variable.previousCurrentVolume[0]) \n }\n else {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[0] - variable.previousCurrentVolume[1])\n }\n}\n\nvariable.bullVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bullPriceRange / totalRange)\nvariable.bearVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bearPriceRange / totalRange)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Open Interest'\n// Converting values to percentages due to the differences of range and volume (range might be in decimals while volume often is in thousands)\n\nif ( candle.close > candle.open && variable.previousCurrentVolume[1] > variable.previousCurrentVolume[0] ) { // Candle UP & Volume UP, Bullish Interest\n variable.openInterest = 1 + ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close < candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle DOWN & Volume DOWN, Bullish Interest\n variable.openInterest = 1 + ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close > candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle UP & Volume DOWN, Bearish Interest\n variable.openInterest = 1 - ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse { // Candle DOWN & Volume UP, Bearish Interest\n variable.openInterest = 1 - ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Saving to arrays\n\nvariable.savedCandleClose.push(candle.close)\nif (variable.savedCandleClose.length > multipliedSlow) {\n variable.savedCandleClose.splice(0, 1)\n}\n\nvariable.savedTotalRange.push(totalRange)\nif (variable.savedTotalRange.length > multipliedSlow) {\n variable.savedTotalRange.splice(0, 1)\n}\n\nvariable.savedBullPriceRange.push(variable.bullPriceRange)\nif (variable.savedBullPriceRange.length > multipliedSlow) {\n variable.savedBullPriceRange.splice(0, 1)\n}\n\nvariable.savedTotalVolume.push(totalVolume)\nif (variable.savedTotalVolume.length > multipliedSlow) {\n variable.savedTotalVolume.splice(0, 1)\n}\n\nvariable.savedOpenInterest.push(variable.openInterest)\nif (variable.savedOpenInterest.length > multipliedSlow) {\n variable.savedOpenInterest.splice(0, 1)\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Calling SMA functions\n\nvariable.smaMultipliedFastCandleClose = calculateSMA(variable.savedCandleClose, multipliedFast)\nvariable.smaSlowCandleClose = calculateSMA(variable.savedCandleClose, slowPeriod)\nvariable.smaLongTermCandleClose = calculateSMA(variable.savedCandleClose, multipliedSlow)\n\nvariable.smaFastTotalRange = calculateSMA(variable.savedTotalRange, fastPeriod)\nvariable.smaSlowTotalRange = calculateSMA(variable.savedTotalRange, slowPeriod)\nvariable.smaLongTermRange = calculateSMA(variable.savedTotalRange, multipliedSlow)\n\nvariable.smaFastBullPriceRange = calculateSMA(variable.savedBullPriceRange, fastPeriod)\nvariable.smaSlowBullPriceRange = calculateSMA(variable.savedBullPriceRange, slowPeriod)\n\nvariable.smaFastTotalVolume = calculateSMA(variable.savedTotalVolume, fastPeriod)\nvariable.smaLongTermTotalVolume = calculateSMA(variable.savedTotalVolume, multipliedSlow)\n\nvariable.smaFastOpenInterest = calculateSMA(variable.savedOpenInterest, fastPeriod)\nvariable.smaSlowOpenInterest = calculateSMA(variable.savedOpenInterest, slowPeriod)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Creating the SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calculation\n if (src.length < periods) { return 0 }\n \n // Initialize sum variable\n let sum = 0 \n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring record variables by comparing 'fastPeriod' values with 'slowPeriod' values, also applying 'fastBoost' and 'gravity'\n\nvariable.fastPriceRange = variable.smaFastTotalRange\nvariable.slowPriceRange = variable.smaSlowTotalRange\nvariable.longTermPriceRange = variable.smaLongTermRange\n\nvariable.bullPriceDeviation = ((((variable.smaFastBullPriceRange * fastBoost) + (variable.smaSlowBullPriceRange * gravity)) / (gravity + 1)) / variable.slowPriceRange) * 2\n\nvariable.volumeDeviation = variable.smaFastTotalVolume / variable.smaLongTermTotalVolume\n\nvariable.openInterestDeviation = ((((variable.smaFastOpenInterest * fastBoost) + (variable.smaSlowOpenInterest * gravity)) / (gravity + 1)) / variable.smaSlowOpenInterest)\n\nvariable.smaPrice = variable.smaMultipliedFastCandleClose / variable.smaLongTermCandleClose\n\n// CJ.","project":"Superalgos","id":"7e403f54-4a96-4d44-b242-bbbf242c3114","savedPayload":{"position":{"x":13686.245899592052,"y":41306.56742651631},"targetPosition":{"x":13763.960495737749,"y":41369.499465621295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5dd4bc88-e9e8-461e-9c87-03c0aeb5f14a","savedPayload":{"position":{"x":13763.960495737749,"y":41369.499465621295},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 6 arrays \n\nvariable.previousCurrentVolume = []\nvariable.savedTotalRange = []\nvariable.savedBullPriceRange = [] \nvariable.savedTotalVolume = [] \nvariable.savedOpenInterest = [] \nvariable.savedCandleClose = [] ","project":"Superalgos","id":"562a1a92-04fd-4126-b3cc-219d21d96607","savedPayload":{"position":{"x":13790.940402569968,"y":41230.50241765447},"targetPosition":{"x":13826.777197524498,"y":41323.86046030419},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"85dd9771-10b0-492c-ace8-0f18fc14d143","savedPayload":{"position":{"x":13826.777197524498,"y":41323.86046030419},"targetPosition":{"x":13880.532389956294,"y":41463.89752427877},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"159c2cf8-383f-4228-9ad5-bc266cd18d5c","savedPayload":{"position":{"x":13880.532389956294,"y":41463.89752427877},"targetPosition":{"x":14056.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"371f636a-012c-4fb8-bf61-c83be358a508","savedPayload":{"position":{"x":14056.867965644036,"y":41706.60262259126},"targetPosition":{"x":14356.867965644036,"y":41706.60262259126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Average VS Average","id":"60771858-6287-419f-b6db-6ab6166063ba"}}}],"id":"3df48abc-f2a5-48ca-bd27-89913fdc0812","savedPayload":{"position":{"x":14356.867965644036,"y":41706.60262259126},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"plotters":[{"type":"Plotter","name":"ARPS Fast Plotter","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS","config":"{\n \"codeName\": \"ARPS-Fast\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"1216597f-916f-40c3-b1cf-9795d7516eb9","savedPayload":{"position":{"x":16921.752452292843,"y":42034.291126365046},"targetPosition":{"x":16621.886722607793,"y":42025.316486514224},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"23be71f9-d898-4182-8fdf-b437ee15d96a","savedPayload":{"position":{"x":16621.886722607793,"y":42025.316486514224},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"96946ddb-82c4-4ded-a55f-f72a64f8b6d0","savedPayload":{"position":{"x":16854.572466325473,"y":42292.727316933786},"targetPosition":{"x":16588.296729624104,"y":42154.534581798594},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0a02c972-ecf7-4263-b396-7ec44323d68b","savedPayload":{"position":{"x":16588.296729624104,"y":42154.534581798594},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"5f7ae8c1-7d37-4d18-b40c-7f65d33a617e","savedPayload":{"position":{"x":16681.914129735487,"y":42496.42197547013},"targetPosition":{"x":16501.967561329115,"y":42256.38191106677},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0958d221-456d-414b-b383-e6fbec8df430","savedPayload":{"position":{"x":16501.967561329115,"y":42256.38191106677},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"0fa59969-0560-4070-8569-674718ff52e5","savedPayload":{"position":{"x":16437.974543600074,"y":42605.03087669991},"targetPosition":{"x":16379.997768261406,"y":42310.686361681655},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bcc803c6-3d10-48dd-82f2-63603a7c3c97","savedPayload":{"position":{"x":16379.997768261406,"y":42310.686361681655},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"d812fcd7-98e8-4c00-a7b3-9711dc93ba86","savedPayload":{"position":{"x":16171.068934676035,"y":42597.042695733806},"targetPosition":{"x":16246.544963799388,"y":42306.69227119861},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c591ce36-7a4f-4ff2-be7c-48e6e7786502","savedPayload":{"position":{"x":16246.544963799388,"y":42306.69227119861},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"92d970a0-e07c-4958-ab07-f4d968d1bf33","savedPayload":{"position":{"x":15934.061232193262,"y":42474.03958978076},"targetPosition":{"x":16128.041112558001,"y":42245.19071822209},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"221a1676-98f3-4175-a301-4f4e85abfe4f","savedPayload":{"position":{"x":16128.041112558001,"y":42245.19071822209},"targetPosition":{"x":16322.02099292274,"y":42016.3418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8a7b65d5-ae94-4075-98d6-1fb143128c07","savedPayload":{"position":{"x":13941.02099292274,"y":42028.34184666341},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"8a3b9f48-6556-4ffc-8694-44db9d0552e3","savedPayload":{"position":{"x":16464.409913763688,"y":42538.924830358024},"targetPosition":{"x":16301.01820325918,"y":42287.3236599744},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f2b46265-4f40-4572-a023-e95007bcbf2a","savedPayload":{"position":{"x":16301.01820325918,"y":42287.3236599744},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"a24fec7c-4b4e-4533-b40b-fe86bb05a8e6","savedPayload":{"position":{"x":16075.252985509345,"y":42329.16676981091},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"23be71f9-d898-4182-8fdf-b437ee15d96a"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"cfccbef2-3746-43c5-8368-fcd84072eec1","savedPayload":{"position":{"x":15886.025322371046,"y":42199.114200095275},"targetPosition":{"x":16137.626492754673,"y":42035.72248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"0a02c972-ecf7-4263-b396-7ec44323d68b"}}}],"id":"b5e43c46-948c-4f56-bfe5-83ba923a20a5","savedPayload":{"position":{"x":13756.626492754673,"y":42047.72248959077},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d8e0d8e9-27ef-4fab-ac43-23868fea8813","savedPayload":{"position":{"x":15945.654978611015,"y":42542.19511213103},"targetPosition":{"x":15961.355765483899,"y":42242.60625170465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"19197333-4a73-4f74-8d05-de667c8d8bf1","savedPayload":{"position":{"x":15961.355765483899,"y":42242.60625170465},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"afc2f8ff-8082-496f-8106-a1f8379cfd12","savedPayload":{"position":{"x":15754.113104713564,"y":42143.75657318594},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"0958d221-456d-414b-b383-e6fbec8df430"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"1606a418-a639-4cd4-909d-de72d689acf0","savedPayload":{"position":{"x":15677.46769193041,"y":41927.3166044054},"targetPosition":{"x":15977.056552356782,"y":41943.017391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"bcc803c6-3d10-48dd-82f2-63603a7c3c97"}}}],"id":"7b2bf0a5-4eb1-4cf6-bb1e-8b7545691dfa","savedPayload":{"position":{"x":13596.056552356782,"y":41955.017391278285},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"0e69ccc1-020e-47e3-9251-1af8231e41c1","savedPayload":{"position":{"x":15524.051196759618,"y":42239.9243252251},"targetPosition":{"x":15712.847314074568,"y":42006.780536788014},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"af7adcc4-8cd2-408f-8550-e017bdbd7d38","savedPayload":{"position":{"x":15712.847314074568,"y":42006.780536788014},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"5b569cf7-d916-4891-9f48-4ffbd9a07acb","savedPayload":{"position":{"x":15603.286862779038,"y":41804.99528733122},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"c591ce36-7a4f-4ff2-be7c-48e6e7786502"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"1197f1d6-2c5f-4c4f-b478-0ff005c8408c","savedPayload":{"position":{"x":15668.499642952427,"y":41584.84063103597},"targetPosition":{"x":15901.643431389519,"y":41773.636748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"221a1676-98f3-4175-a301-4f4e85abfe4f"}}}],"id":"0dbddbd2-336e-4495-adee-2cb008743b39","savedPayload":{"position":{"x":13520.643431389519,"y":41785.636748350924},"targetPosition":{"x":13819,"y":41754.27820937063},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"ab1a9808-3321-487e-a4ee-598cbe1e06e6","savedPayload":{"position":{"x":13819,"y":41754.27820937063},"targetPosition":{"x":13969,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS","config":"{\n \"codeName\": \"ARPS\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"40a7c8ec-adfa-4319-afbb-4fdce8d83548","savedPayload":{"position":{"x":13239.444504226558,"y":41234.66296709996},"targetPosition":{"x":13529.222252113279,"y":41157.0172535692},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"485aa9f4-e9cb-4734-883f-8a3f68a2f054","savedPayload":{"position":{"x":13317.090217757315,"y":40944.88521921324},"targetPosition":{"x":13529.222252113279,"y":41157.0172535692},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"9cdae6f2-28fd-47bc-930d-3454aa053de4","savedPayload":{"position":{"x":13529.222252113279,"y":41157.0172535692},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"6d06c410-c7fc-46d9-a935-5125326f4ff6","savedPayload":{"position":{"x":13409.192378864669,"y":40824.85534596463},"targetPosition":{"x":13669,"y":40974.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"567e7a98-a673-46ad-9b48-64c55f4e2c91","savedPayload":{"position":{"x":13669,"y":40674.85534596463},"targetPosition":{"x":13669,"y":40974.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"da3f2ea2-6452-4f7a-afd0-c91bb3915956","savedPayload":{"position":{"x":13669,"y":40974.85534596463},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"8bb34797-b438-46b7-98ac-13626abeb3d9","savedPayload":{"position":{"x":13819,"y":40655.10747132652},"targetPosition":{"x":13896.645713530756,"y":40944.88521921324},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"fc5e8a98-9891-4c4e-aaf4-3b1d485c1d0d","savedPayload":{"position":{"x":14108.77774788672,"y":40732.753184857276},"targetPosition":{"x":13896.645713530756,"y":40944.88521921324},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e738ec96-c711-4b1d-9689-7bbe923b84db","savedPayload":{"position":{"x":13896.645713530756,"y":40944.88521921324},"targetPosition":{"x":13819,"y":41234.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"97906f34-67ef-438b-85a7-59cebfd1dcfb","savedPayload":{"position":{"x":13819,"y":41234.66296709996},"targetPosition":{"x":13969,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2675db9e-a697-4f84-a252-8c27ed423e24","savedPayload":{"position":{"x":13969,"y":41494.470588235294},"targetPosition":{"x":14269,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e9b75238-86e2-4069-8f82-d8884bf729ee","savedPayload":{"position":{"x":14269,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Chaikin Oscillator Plotter","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.zeroLine","project":"Superalgos","id":"fec8363f-45ef-4e43-850a-4102ae1d1f62","savedPayload":{"position":{"x":15743.934675239096,"y":41002.99424592844},"targetPosition":{"x":15977.078463676187,"y":40814.19812861349},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b4d7a68b-446d-4aab-938b-3da564ec607d","savedPayload":{"position":{"x":15977.078463676187,"y":40814.19812861349},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.zeroLine","project":"Superalgos","id":"3db966a2-1491-4758-a29f-e6caedcf2208","savedPayload":{"position":{"x":15611.044531260533,"y":40656.803585044305},"targetPosition":{"x":15910.633391686906,"y":40641.10279817142},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"013e2783-f200-4b83-b914-91aefd6e7e6f","savedPayload":{"position":{"x":15910.633391686906,"y":40641.10279817142},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.chaikinOscillator","project":"Superalgos","id":"78359bae-9317-4916-a89f-d41d00a24627","savedPayload":{"position":{"x":15707.019911346026,"y":40298.61859028952},"targetPosition":{"x":15958.621081729652,"y":40462.010300794034},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b159f5cc-42a5-498f-a699-f033248a7eb1","savedPayload":{"position":{"x":15958.621081729652,"y":40462.010300794034},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.chaikinOscillator","project":"Superalgos","id":"2384e88c-6e7a-4635-bb62-361dd0edda7d","savedPayload":{"position":{"x":15995.201482386099,"y":40065.25375540022},"targetPosition":{"x":16102.711867249689,"y":40345.32788334938},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"00cac505-e6ac-44b5-bc76-1e88a17ebd88","savedPayload":{"position":{"x":16102.711867249689,"y":40345.32788334938},"targetPosition":{"x":16210.222252113279,"y":40625.40201129854},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"2fba905c-acdb-4217-ba62-2e762b1ddeec","savedPayload":{"position":{"x":16210.222252113279,"y":40625.40201129854},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d2054636-c85e-49df-ab90-313851dfcc4c","savedPayload":{"position":{"x":15770.444504226558,"y":40287.94867663245},"targetPosition":{"x":16060.222252113279,"y":40365.594390163205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d3277379-9eb1-4fca-b134-c4dcdf45d532","savedPayload":{"position":{"x":16060.222252113279,"y":40365.594390163205},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"3b89ce9b-df0f-4fb3-b181-deb5d6926262","savedPayload":{"position":{"x":16200,"y":40183.43248255863},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"b4d7a68b-446d-4aab-938b-3da564ec607d"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"93d7041c-5f20-4b85-9f7a-f16d6427d7b2","savedPayload":{"position":{"x":16427.645713530757,"y":40153.46235580724},"targetPosition":{"x":16350,"y":40443.24010369396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"013e2783-f200-4b83-b914-91aefd6e7e6f"}}}],"id":"bad71c42-7ad3-41df-9634-9599e0cd59c7","savedPayload":{"position":{"x":16350,"y":40443.24010369396},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"Chaikin Oscillator","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"d35e45c5-146b-41a2-8973-06c7dabc010b","savedPayload":{"position":{"x":16277.645713530756,"y":39893.65473467191},"targetPosition":{"x":16427.645713530757,"y":40153.46235580724},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d746e2c7-aae0-4c83-a1a2-23a1d779173c","savedPayload":{"position":{"x":16427.645713530757,"y":40153.46235580724},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Chaikin Oscillator Begin","project":"Superalgos","id":"cc9ee8d7-5b93-4c3b-a700-db3776fbe24a","savedPayload":{"position":{"x":16655.29142706151,"y":40123.49222905585},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator Begin","id":"b159f5cc-42a5-498f-a699-f033248a7eb1"}}},{"type":"Polygon Vertex","name":"Chaikin Oscillator End","project":"Superalgos","id":"e9007c32-1519-497a-bed3-7eaa3f60ccff","savedPayload":{"position":{"x":16837.453334666086,"y":40263.269976942574},"targetPosition":{"x":16577.645713530757,"y":40413.269976942574},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator End","id":"00cac505-e6ac-44b5-bc76-1e88a17ebd88"}}}],"id":"78c2a948-2c47-40c9-89d8-00d7992cb17c","savedPayload":{"position":{"x":16577.645713530757,"y":40413.269976942574},"targetPosition":{"x":16500,"y":40703.047724829295},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"6f0e43ac-96e8-490f-9d08-8c7489a6614c","savedPayload":{"position":{"x":16500,"y":40703.047724829295},"targetPosition":{"x":16650,"y":40962.85534596463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"653018cc-a18a-4370-a6c5-e0ad879b2c2f","savedPayload":{"position":{"x":16650,"y":40962.85534596463},"targetPosition":{"x":16800,"y":41222.66296709996},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"412c32ee-724a-4b58-9fef-58ecf975de8b","savedPayload":{"position":{"x":14356.867965644036,"y":41282.33855387933},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Slow Plotter","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"ca8a3ebb-25b0-4359-b3c5-218fc7ee69a0","savedPayload":{"position":{"x":16845.752452292843,"y":42258.791126365046},"targetPosition":{"x":16545.886722607793,"y":42249.816486514224},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"e5da7299-927f-46e1-95a0-18230e59af0e","savedPayload":{"position":{"x":16545.886722607793,"y":42249.816486514224},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"f9baacc0-6c94-421b-8a65-629e37e19e7d","savedPayload":{"position":{"x":16778.572466325473,"y":42517.227316933786},"targetPosition":{"x":16512.296729624104,"y":42379.034581798594},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1fa7c445-e500-44ac-94d2-1f4f8b4a4a32","savedPayload":{"position":{"x":16512.296729624104,"y":42379.034581798594},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"89b91ab8-fd0b-4f22-885e-968f84dba9db","savedPayload":{"position":{"x":16605.914129735487,"y":42720.92197547013},"targetPosition":{"x":16425.96756132911,"y":42480.88191106677},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"3ec07cce-c6fd-4e38-9581-20665a1f42e3","savedPayload":{"position":{"x":16425.96756132911,"y":42480.88191106677},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"6bff0f0a-5220-41a3-b785-0c3fdc0d7c22","savedPayload":{"position":{"x":16361.974543600072,"y":42829.53087669991},"targetPosition":{"x":16303.997768261404,"y":42535.186361681655},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b9fcdbe-6783-4719-b3ca-a8811b2ef7e6","savedPayload":{"position":{"x":16303.997768261404,"y":42535.186361681655},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"2a45e116-9295-46fe-beb5-e97bb88fa18f","savedPayload":{"position":{"x":16095.068934676034,"y":42821.542695733806},"targetPosition":{"x":16170.544963799386,"y":42531.19227119861},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b1673c67-03d9-4f80-b7d7-6ea05d917b9a","savedPayload":{"position":{"x":16170.544963799386,"y":42531.19227119861},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"9b122b4f-ea2b-426b-8b72-e57e62688280","savedPayload":{"position":{"x":15858.06123219326,"y":42698.53958978076},"targetPosition":{"x":16052.041112558,"y":42469.69071822209},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1a63a717-1978-47a8-9b3d-50995f7d77a9","savedPayload":{"position":{"x":16052.041112558,"y":42469.69071822209},"targetPosition":{"x":16246.020992922739,"y":42240.8418466634},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"c574a116-3471-454e-aa91-939ea988d761","savedPayload":{"position":{"x":14635.54422723201,"y":40672.91838677305},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"722a1147-5e6d-4b23-8f45-61450a7d0b00","savedPayload":{"position":{"x":16388.409913763688,"y":42763.424830358024},"targetPosition":{"x":16225.018203259178,"y":42511.8236599744},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"4383c9dd-82d5-494b-aef3-5df2cc85d159","savedPayload":{"position":{"x":16225.018203259178,"y":42511.8236599744},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"1e9c722a-92cc-4189-836f-53ad2dc7938f","savedPayload":{"position":{"x":15999.252985509343,"y":42553.66676981091},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"e5da7299-927f-46e1-95a0-18230e59af0e"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"2f93dabf-aae9-44e0-9273-8124fcdc3dab","savedPayload":{"position":{"x":15810.025322371044,"y":42423.614200095275},"targetPosition":{"x":16061.62649275467,"y":42260.22248959077},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"1fa7c445-e500-44ac-94d2-1f4f8b4a4a32"}}}],"id":"2490ae4c-0fce-4ad1-85bc-a651044a408c","savedPayload":{"position":{"x":14752.226644676664,"y":40528.82760125302},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"4a8be682-30e9-4595-8fd7-a7bdd5275af8","savedPayload":{"position":{"x":15869.654978611014,"y":42766.69511213103},"targetPosition":{"x":15885.355765483897,"y":42467.10625170465},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"106b5fd8-64f3-4731-96e3-641dddb9bb06","savedPayload":{"position":{"x":15885.355765483897,"y":42467.10625170465},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"1e039cea-279e-4319-a562-65d2b3e42415","savedPayload":{"position":{"x":15678.113104713562,"y":42368.25657318594},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"3ec07cce-c6fd-4e38-9581-20665a1f42e3"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"667f6ce6-e9c3-4485-89bd-270311441baf","savedPayload":{"position":{"x":15601.467691930407,"y":42151.8166044054},"targetPosition":{"x":15901.05655235678,"y":42167.517391278285},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"1b9fcdbe-6783-4719-b3ca-a8811b2ef7e6"}}}],"id":"0f06b5f2-e742-4520-8e0e-6a7e9bd4974e","savedPayload":{"position":{"x":14931.319142054055,"y":40480.83991121027},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"153aa0a3-9042-429c-9eae-dc5385217116","savedPayload":{"position":{"x":15448.051196759616,"y":42464.4243252251},"targetPosition":{"x":15636.847314074566,"y":42231.280536788014},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f031e2cb-6fb6-469d-8baa-bcfe24dec1c3","savedPayload":{"position":{"x":15636.847314074566,"y":42231.280536788014},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"03a063b9-6203-4384-b89e-e85341b0cb24","savedPayload":{"position":{"x":15527.286862779036,"y":42029.49528733122},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"b1673c67-03d9-4f80-b7d7-6ea05d917b9a"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"2507628c-b9e6-4103-9c94-21abc3489762","savedPayload":{"position":{"x":15592.499642952425,"y":41809.34063103597},"targetPosition":{"x":15825.643431389517,"y":41998.136748350924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"1a63a717-1978-47a8-9b3d-50995f7d77a9"}}}],"id":"7c0e4100-b3c1-4e60-85f1-1d9e1bd6f7fd","savedPayload":{"position":{"x":15104.414472496122,"y":40547.284983199555},"targetPosition":{"x":14915.618355181172,"y":40780.428771636645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"aeebf45e-fe48-4377-a483-c9c67690a62f","savedPayload":{"position":{"x":14915.618355181172,"y":40780.428771636645},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS","config":"{\n \"codeName\": \"ARPS\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"61766652-706a-4bb9-87ef-2d6e6943d853","savedPayload":{"position":{"x":15692.84943773398,"y":40738.04461191879},"targetPosition":{"x":15542.84943773398,"y":40997.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"51875264-c8ee-4839-aa4d-1b9b71d891ff","savedPayload":{"position":{"x":15842.84943773398,"y":40997.852233054124},"targetPosition":{"x":15542.84943773398,"y":40997.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b4f7f01-5b42-4954-8668-3cbda5b77063","savedPayload":{"position":{"x":15542.84943773398,"y":40997.852233054124},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"e9c52716-c5f2-4624-ba6e-c173c7f7dbfd","savedPayload":{"position":{"x":15862.59731237209,"y":41147.852233054124},"targetPosition":{"x":15572.81956448537,"y":41225.49794658488},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"7feaef19-3ea1-4124-8aa4-afd75c5816f1","savedPayload":{"position":{"x":15784.951598841333,"y":41437.629980940845},"targetPosition":{"x":15572.81956448537,"y":41225.49794658488},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bce58d87-f0fc-4515-ab47-1d5d57162bac","savedPayload":{"position":{"x":15572.81956448537,"y":41225.49794658488},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"e00cdf0d-5b55-4ce1-a960-bae254b568dd","savedPayload":{"position":{"x":15692.84943773398,"y":41557.65985418946},"targetPosition":{"x":15433.041816598648,"y":41407.65985418946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"f7999c40-89bc-4c73-9ea5-1b2266814a5c","savedPayload":{"position":{"x":15433.041816598648,"y":41707.65985418946},"targetPosition":{"x":15433.041816598648,"y":41407.65985418946},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"dd112929-5166-4ac7-9c61-9158e3eab9e0","savedPayload":{"position":{"x":15433.041816598648,"y":41407.65985418946},"targetPosition":{"x":15283.041816598648,"y":41147.852233054124},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1e96ebb8-5d70-440d-977f-1781f746f31a","savedPayload":{"position":{"x":15283.041816598648,"y":41147.852233054124},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ba1f7fe7-29a3-4cf2-b185-dc2c65e5cc5a","savedPayload":{"position":{"x":14993.264068711927,"y":41070.206519523366},"targetPosition":{"x":14781.132034355964,"y":41282.33855387933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"75c554ed-b9fd-4fb9-9f27-7d6e5e665f8a","savedPayload":{"position":{"x":14569,"y":41194.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Average VS Average Plotter","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = 1","project":"Superalgos","id":"5ebd08dc-c6b9-4429-92c5-b44e86727d6a","savedPayload":{"position":{"x":14886.480951457786,"y":41080.62920696757},"targetPosition":{"x":15113.94976613913,"y":40692.35361109852},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9","savedPayload":{"position":{"x":15113.94976613913,"y":40692.35361109852},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = 1","project":"Superalgos","id":"246941f4-3c18-4ca4-be0f-e8cef636bec1","savedPayload":{"position":{"x":14686.129369247508,"y":40921.00268583042},"targetPosition":{"x":15013.773975033992,"y":40612.54035052995},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c575e8b4-3491-4533-be08-fae19636edd9","savedPayload":{"position":{"x":15013.773975033992,"y":40612.54035052995},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.bullPriceDeviation","project":"Superalgos","id":"e7e97620-5c89-4806-8855-1118189cca8c","savedPayload":{"position":{"x":14538.865421803868,"y":40711.396596873456},"targetPosition":{"x":14940.142001312171,"y":40507.737306051466},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5856cd48-be9d-43a4-ab20-5215f4d8008f","savedPayload":{"position":{"x":14940.142001312171,"y":40507.737306051466},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.bullPriceDeviation","project":"Superalgos","id":"1fea2d4e-6680-48ab-b7c8-385f26b473d7","savedPayload":{"position":{"x":14456.61955833634,"y":40468.79197884859},"targetPosition":{"x":14899.019069578408,"y":40386.43499703903},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0f7c9019-cf97-455b-997b-23bb7fd5ee8d","savedPayload":{"position":{"x":14899.019069578408,"y":40386.43499703903},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.volumeDeviation","project":"Superalgos","id":"7bd64bdc-26e2-473e-b6b4-dfd9a1b90395","savedPayload":{"position":{"x":14446.054849568074,"y":40212.84321508295},"targetPosition":{"x":14893.736715194274,"y":40258.46061515621},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff","savedPayload":{"position":{"x":14893.736715194274,"y":40258.46061515621},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.volumeDeviation","project":"Superalgos","id":"da79b97b-1844-4fda-89ee-ad427795597e","savedPayload":{"position":{"x":14508.027185372732,"y":39964.285752230935},"targetPosition":{"x":14924.722883096603,"y":40134.181883730205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4","savedPayload":{"position":{"x":14924.722883096603,"y":40134.181883730205},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.openInterestDeviation","project":"Superalgos","id":"d1dea870-5cc2-40ec-a697-16f607c5d976","savedPayload":{"position":{"x":14637.515935667096,"y":39743.25623770467},"targetPosition":{"x":14989.467258243785,"y":40023.66712646707},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"01f5ed3c-22df-4a5e-bc9a-1c1bcd82e187","savedPayload":{"position":{"x":14989.467258243785,"y":40023.66712646707},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.openInterestDeviation","project":"Superalgos","id":"9516a25e-3b91-4d82-a02f-6ec800fdfdff","savedPayload":{"position":{"x":14824.030692001568,"y":39567.661168257924},"targetPosition":{"x":15082.724636411021,"y":39935.8695917437},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5f18a8ed-6d3a-4e97-b2c7-8833ae328ee0","savedPayload":{"position":{"x":15082.724636411021,"y":39935.8695917437},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.smaPrice","project":"Superalgos","id":"de1c3212-9782-4dd2-b7a6-6d1215fcaa4f","savedPayload":{"position":{"x":15052.461138063893,"y":39451.72621211319},"targetPosition":{"x":15196.939859442184,"y":39877.902113671335},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ae121f69-414a-4593-bee4-3f42c4855e75","savedPayload":{"position":{"x":15196.939859442184,"y":39877.902113671335},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.smaPrice","project":"Superalgos","id":"8c70536b-5484-4c7f-a7d9-1a4b83f180f4","savedPayload":{"position":{"x":15304.301197642275,"y":39404.84372992559},"targetPosition":{"x":15322.859889231375,"y":39854.46087257753},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b413b15-e479-4d18-9c8e-0cc067c791eb","savedPayload":{"position":{"x":15322.859889231375,"y":39854.46087257753},"targetPosition":{"x":15341.418580820475,"y":40304.078015229476},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"61cb4958-a145-4e5b-ac3d-976868a2bbb3","savedPayload":{"position":{"x":15015.217885284577,"y":40450.23598100091},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"a2aa7fc6-9333-44d9-a272-79da7527502a","savedPayload":{"position":{"x":14967.529071742714,"y":40194.74209150929},"targetPosition":{"x":15267.520679261095,"y":40196.986065336605},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"cef91315-4506-4374-83a2-c899fcdec3a3","savedPayload":{"position":{"x":15267.520679261095,"y":40196.986065336605},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"b8cb8331-a6ec-4693-81e5-0c518f8d3bf7","savedPayload":{"position":{"x":15356.972915914279,"y":39985.51721007852},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"5fb2e9a0-5ae9-4132-9309-4ed517d26111","savedPayload":{"position":{"x":15569.756260606797,"y":39899.23843164554},"targetPosition":{"x":15567.512286779476,"y":40199.23003916392},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}}],"id":"cca59d3d-d290-4534-802f-8b20224875d7","savedPayload":{"position":{"x":15179.249380243593,"y":40559.21607573988},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice > record.previous.smaPrice","project":"Superalgos","id":"f3e0632e-6cf2-4f0b-bef7-82b15c1c4795","savedPayload":{"position":{"x":15310.005105837628,"y":40240.27137909361},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"8ce4673b-02f7-4fdd-a41a-68bd3603eb11","savedPayload":{"position":{"x":15009.10307759985,"y":40076.377090912705},"targetPosition":{"x":15305.40957977839,"y":40123.30743042477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"b0533485-c84c-492b-be01-f5da1e7acfa0","savedPayload":{"position":{"x":15305.40957977839,"y":40123.30743042477},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"4a3ebec3-46cf-424b-8b19-3246dcd527b6","savedPayload":{"position":{"x":15090.131983344474,"y":39856.73863110726},"targetPosition":{"x":15345.924032650702,"y":40013.48820052205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"968cf63e-2566-4697-92c2-4e9a01de083a","savedPayload":{"position":{"x":15345.924032650702,"y":40013.48820052205},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"960b6798-dc4b-4ccf-a1d2-8d114b228ba4","savedPayload":{"position":{"x":15425.380506269188,"y":39927.53267162435},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"ae121f69-414a-4593-bee4-3f42c4855e75"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"ec3a86be-3906-4395-ad66-22974b63e702","savedPayload":{"position":{"x":15531.68247280016,"y":39878.52679381753},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"1b413b15-e479-4d18-9c8e-0cc067c791eb"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"47505d15-f5cd-4eed-a2ca-0e19e1fd5425","savedPayload":{"position":{"x":15648.646421469,"y":39873.93126775829},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"a95edd6e-9ac7-4c4b-8d44-2ea5d4c91126","savedPayload":{"position":{"x":15758.465651371716,"y":39914.44572063061},"targetPosition":{"x":15601.71608195693,"y":40170.23776993684},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}}],"id":"0b45de42-16c8-4845-9634-0c4594a848a5","savedPayload":{"position":{"x":15283.041816598647,"y":40568.29673728068},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice < record.previous.smaPrice","project":"Superalgos","id":"ba7bc4d2-ea9d-46e5-8a46-4076b973082d","savedPayload":{"position":{"x":15397.288894196598,"y":40090.60339533746},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"c397754e-7f7f-4101-85bc-ce03e0560cd1","savedPayload":{"position":{"x":15170.588626615936,"y":39833.67858732003},"targetPosition":{"x":15432.974538757755,"y":39979.12147339393},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f869822a-1175-4ca9-b1ab-0eb6c8e8aa21","savedPayload":{"position":{"x":15432.974538757755,"y":39979.12147339393},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"45046251-89ef-4e4a-a6ad-508940e81d8b","savedPayload":{"position":{"x":15321.851668917003,"y":39654.99946535638},"targetPosition":{"x":15508.606059908288,"y":39889.7819124121},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d72f0442-35cd-4291-9ed0-2d18974d8622","savedPayload":{"position":{"x":15508.606059908288,"y":39889.7819124121},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"1de42509-51b7-4db5-bb4b-ec99f020f67f","savedPayload":{"position":{"x":15612.669244154475,"y":39836.18585068633},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"ae121f69-414a-4593-bee4-3f42c4855e75"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"086e31ca-712a-4a76-bfde-85f94a0c1f3d","savedPayload":{"position":{"x":15729.321415029946,"y":39826.49280276485},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"1b413b15-e479-4d18-9c8e-0cc067c791eb"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"d2474336-018f-4a72-b944-8cca376adeab","savedPayload":{"position":{"x":15840.803336973475,"y":39862.178447326005},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"61bd3a59-9a0b-45bf-8541-69e9cce47c5b","savedPayload":{"position":{"x":15930.142897955298,"y":39937.80996847654},"targetPosition":{"x":15695.360450899574,"y":40124.564359467826},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}}],"id":"7c193813-cccc-44d2-aa9d-0896829f042b","savedPayload":{"position":{"x":15377.469033973204,"y":40612.3288718807},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation > record.previous.volumeDeviation","project":"Superalgos","id":"7d0a809e-062d-422f-8b7d-10485a9f795b","savedPayload":{"position":{"x":15538.426213757815,"y":39964.97108377715},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"e43653a6-3d17-4654-b54a-df888f3c6314","savedPayload":{"position":{"x":15458.518676912643,"y":39619.62199501265},"targetPosition":{"x":15628.748638340277,"y":39866.64782409201},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"0d23723f-0ff9-45ad-87df-48ea3e1c2303","savedPayload":{"position":{"x":15628.748638340277,"y":39866.64782409201},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"31da194c-7e54-492e-ad59-4de79fd948f2","savedPayload":{"position":{"x":15752.787194516952,"y":39817.25105942903},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"610ad563-a4f0-4056-b455-f8769a6b14c5","savedPayload":{"position":{"x":15885.974525003989,"y":39826.56442484125},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"88f8f21a-a2a3-4495-b6b5-87535eba5707","savedPayload":{"position":{"x":16001.931245563013,"y":39892.743294087864},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"a5449c88-9bfc-4dea-b10b-7d52c7033224","savedPayload":{"position":{"x":16077.690705571462,"y":40002.68013048401},"targetPosition":{"x":15798.978599767912,"y":40113.673653171376},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff"}}}],"id":"471faeec-673f-4e1b-b09e-876a5a47fc26","savedPayload":{"position":{"x":15451.141716354588,"y":40686.00155426209},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation < record.previous.volumeDeviation","project":"Superalgos","id":"d6e67762-8e26-49eb-9dfb-76e9f91ce637","savedPayload":{"position":{"x":15464.277178666107,"y":40013.38730342399},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"6a4f75ce-c32a-4c6d-abf4-ca5930321ad4","savedPayload":{"position":{"x":15325.614376933983,"y":39687.160641468035},"targetPosition":{"x":15536.15374779918,"y":39900.87347055344},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8d9386bd-34ff-4935-9ff4-bf8c61aaa81e","savedPayload":{"position":{"x":15536.15374779918,"y":39900.87347055344},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"95297404-bf72-4524-b035-271c2077d97a","savedPayload":{"position":{"x":15649.730221428039,"y":39830.68808449909},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"afd0f39f-5fc0-4d14-b192-818f6d7ff2b9"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"af1b8269-e003-490a-8615-db6ee76fc758","savedPayload":{"position":{"x":15782.511386026452,"y":39816.73222173629},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"c575e8b4-3491-4533-be08-fae19636edd9"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"6fd2d967-3262-4e23-807a-55ea30878977","savedPayload":{"position":{"x":15908.198303491583,"y":39861.77001204262},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"55ea7fa6-9f58-4dad-b95b-6800ec0046d4"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"4cdb7b68-9c6b-42ac-be3a-6de38cd9674f","savedPayload":{"position":{"x":16001.89713837058,"y":39956.88116869569},"targetPosition":{"x":15746.693118664378,"y":40114.58629963884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"48b16beb-f1d0-46df-ab29-5c6d43a905ff"}}}],"id":"0f21f203-c9c7-49b9-a385-2c35777d29f7","savedPayload":{"position":{"x":15495.173850954612,"y":40780.428771636645},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"openInterestDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 2,\n 7\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"a4cb8a9f-a8b0-4a8a-aec3-943acf806a1a","savedPayload":{"position":{"x":15975.977724920001,"y":39597.23231105389},"targetPosition":{"x":15981.213446851187,"y":39897.18661960081},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"3713f189-0b41-47c9-9c2e-298c552add2a","savedPayload":{"position":{"x":15981.213446851187,"y":39897.18661960081},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"openInterestDeviation Begin","project":"Superalgos","id":"350b9484-0724-4be2-874e-ca36e33624cd","savedPayload":{"position":{"x":16194.84667992007,"y":39981.33898804614},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation Begin","id":"01f5ed3c-22df-4a5e-bc9a-1c1bcd82e187"}}},{"type":"Polygon Vertex","name":"openInterestDeviation End","project":"Superalgos","id":"faa57ea2-d4ae-4e99-a3c5-8f4c81b4a34a","savedPayload":{"position":{"x":16286.40347732929,"y":40191.90520621655},"targetPosition":{"x":15986.449168782372,"y":40197.14092814773},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation End","id":"5f18a8ed-6d3a-4e97-b2c7-8833ae328ee0"}}}],"id":"7f7d3fc6-4d2a-4089-bcf7-a16c360c5d22","savedPayload":{"position":{"x":15504.254512495414,"y":40884.2212079917},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"bullPriceDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 3,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"c4087104-30ad-4af1-8803-59af51da41f3","savedPayload":{"position":{"x":16243.030764208715,"y":39714.12037885301},"targetPosition":{"x":16145.36031787157,"y":39997.77595153281},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d8c419ea-638b-43bc-923e-eed6ed4f37ee","savedPayload":{"position":{"x":16145.36031787157,"y":39997.77595153281},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"bullPriceDeviation Begin","project":"Superalgos","id":"334d6bde-0a67-4e7e-b0df-3c28eed184b9","savedPayload":{"position":{"x":16317.328085424173,"y":40149.92018017588},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation Begin","id":"5856cd48-be9d-43a4-ab20-5215f4d8008f"}}},{"type":"Polygon Vertex","name":"bullPriceDeviation End","project":"Superalgos","id":"be73fa5c-820b-431b-9eba-a7a4a899335a","savedPayload":{"position":{"x":16331.345444214217,"y":40379.10197054975},"targetPosition":{"x":16047.689871534423,"y":40281.4315242126},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation End","id":"0f7c9019-cf97-455b-997b-23bb7fd5ee8d"}}}],"id":"5d8bc357-8920-4c8f-b491-d7441fbc1116","savedPayload":{"position":{"x":15477.288439178887,"y":40984.85996368961},"targetPosition":{"x":15205.396103067891,"y":40858.0744851674},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"4fab7c9a-d0ea-4a8b-ba5e-b542d1f03aad","savedPayload":{"position":{"x":15205.396103067891,"y":40858.0744851674},"targetPosition":{"x":14993.264068711927,"y":41070.206519523366},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"60771858-6287-419f-b6db-6ab6166063ba","savedPayload":{"position":{"x":14993.264068711927,"y":41070.206519523366},"targetPosition":{"x":14781.132034355964,"y":41282.33855387933},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3a455597-8c02-4f2f-acb0-031e12ecc725","savedPayload":{"position":{"x":14781.132034355964,"y":41282.33855387933},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"326278f7-adb0-4a6f-b606-1313b910818a","savedPayload":{"position":{"x":14569,"y":41494.470588235294},"targetPosition":{"x":14569,"y":41494.470588235294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}} \ No newline at end of file From e9c00276b77af46b834554277371447f93a34309 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:27:44 +0200 Subject: [PATCH 18/32] Delete Omega One.json --- Projects/Superalgos/Plugins/Data-Mines/Omega One.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Projects/Superalgos/Plugins/Data-Mines/Omega One.json diff --git a/Projects/Superalgos/Plugins/Data-Mines/Omega One.json b/Projects/Superalgos/Plugins/Data-Mines/Omega One.json deleted file mode 100644 index c9f447b78..000000000 --- a/Projects/Superalgos/Plugins/Data-Mines/Omega One.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"Data Mine","name":"Omega One","config":"{\n \"codeName\": \"Omega-One\"\n}","project":"Superalgos","sensorBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Chaikin Oscillator","project":"Superalgos","id":"130f1639-b299-4ca8-96eb-25c8345e09e4","savedPayload":{"position":{"x":13957.729481237811,"y":17901.141979655422},"targetPosition":{"x":14015.96376638588,"y":18118.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"5b0389ae-3da9-4628-bc20-1041faef76be"}}}],"outputDatasetFolders":[],"id":"e54488da-6999-437b-8a2d-85709728bb02","savedPayload":{"position":{"x":14015.96376638588,"y":18118.475290570463},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"1ff01e67-048e-4d80-a944-b1b86f21f42b","savedPayload":{"position":{"x":14143.886491396086,"y":17681.058769490315},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"c4fcc40a-427d-4c69-90a9-76abdc87b857","savedPayload":{"position":{"x":14214.185526065303,"y":17677.374553197562},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"2cb0d0f1-a9dc-4791-9952-0878eeaa96bd","savedPayload":{"position":{"x":14282.182366522136,"y":17695.594251685838},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"6e898c07-cb2e-4589-bd33-9b3c6b585bae","savedPayload":{"position":{"x":14341.221008260825,"y":17733.93439392301},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"2ea98444-5707-42c3-a6d0-0c4d7cceec15","savedPayload":{"position":{"x":14190.666621830082,"y":17901.141979655422},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74","savedPayload":{"position":{"x":14392.396103067893,"y":18017.610549951558},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"4a247a06-dfc4-400b-a3b8-fa9d57847f6a","savedPayload":{"position":{"x":14291.531362448988,"y":18277.574316337435},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"9d6d825e-c8cf-4d42-828c-62a1ba12bd32","savedPayload":{"position":{"x":14291.531362448988,"y":18394.04288663357},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e51bc1f1-1063-4d69-9699-3952ad33a056","savedPayload":{"position":{"x":14074.198051533947,"y":18335.808601485503},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Chaikin Oscillator","project":"Superalgos","id":"3d8886e0-c7a2-43aa-91c4-7698757a50e8","savedPayload":{"position":{"x":14656.000000000002,"y":17874.58378961345},"targetPosition":{"x":14431.000000000002,"y":18264.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108"}}}],"outputDatasetFolders":[],"id":"7ed09a77-8e5a-4f61-a182-ed93aa9e8037","savedPayload":{"position":{"x":14431.000000000002,"y":18264.29522131645},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Daily","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"61339b0d-ee5d-4848-a59c-b3f6d5ecfc07","savedPayload":{"position":{"x":14820.711431703,"y":18039.29522131645},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"21243e1a-a52f-40f7-9087-483a49a574a8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"b0e714a3-f496-407a-b1e5-b722df1b8e96","savedPayload":{"position":{"x":14913.909483236945,"y":18110.808601485503},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{\n \"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"7ddfb356-e8b3-4e49-9642-670f81d29b29","savedPayload":{"position":{"x":14985.422863405996,"y":18204.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"3ed165f6-6c65-445f-b70a-70275435ffca","savedPayload":{"position":{"x":15030.37805353308,"y":18312.538082723313},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"d9dc3be3-7565-4801-9d18-2b25380dcf87","savedPayload":{"position":{"x":15045.711431703,"y":18429.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"50b4b77b-7aae-4fb8-b147-4e77438e3278","savedPayload":{"position":{"x":14595.711431703,"y":18429.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"21243e1a-a52f-40f7-9087-483a49a574a8","savedPayload":{"position":{"x":14656.000000000002,"y":18654.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"124bcc91-61a1-40a1-a0b8-08179b8c16f6","savedPayload":{"position":{"x":14400.855715851501,"y":18766.50665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"ffa4c8b2-81bc-4f09-a54b-7fc71543b8f5","savedPayload":{"position":{"x":14318.500000000002,"y":18848.86236887095},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9c9a84d7-7bcf-4ffa-96db-a4a0b51d8e93","savedPayload":{"position":{"x":14206.000000000002,"y":18654.00665301945},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"singularVariableName\": \"chaikinOscillator\",\n \"pluralVariableName\": \"chaikinOscillators\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"5b0389ae-3da9-4628-bc20-1041faef76be","savedPayload":{"position":{"x":14264.438536534506,"y":18819.208347863343},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108","savedPayload":{"position":{"x":14235.433991612475,"y":19002.335837297276},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"3b204f99-f7d6-4d97-96f5-9e0f6cbc0558","savedPayload":{"position":{"x":14833.139338556775,"y":19494.60328091257},"targetPosition":{"x":14536.832836378235,"y":19447.672941400502},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cc3721e3-1409-4d80-8b1d-2d76ee03aefa","savedPayload":{"position":{"x":14536.832836378235,"y":19447.672941400502},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"a7081fb9-9143-463f-8e64-270dda8190dc","savedPayload":{"position":{"x":14664.790402911622,"y":19825.00667060036},"targetPosition":{"x":14452.658368555658,"y":19612.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"128aca84-d3ff-45ec-a8d2-b1fd4e942274","savedPayload":{"position":{"x":14452.658368555658,"y":19612.874636244396},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if ( isNaN(variable.chaikinOscillator ) )\n{ variable.chaikinOscillator = 0 }\nelse\n{ variable.chaikinOscillator }","project":"Superalgos","id":"eefbdfb1-b1b7-46c9-b283-f6de0dd556d1","savedPayload":{"position":{"x":14310.921843467799,"y":19845.202355156245},"targetPosition":{"x":14287.456673711764,"y":19697.049104066973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7f4e57b6-1d97-4902-8c5b-04d0ddaac1e6","savedPayload":{"position":{"x":14287.456673711764,"y":19697.049104066973},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Zero Line","config":"{\n \"codeName\": \"zeroLine\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"0","project":"Superalgos","id":"45c55257-fc58-4b76-9310-6471ff58182a","savedPayload":{"position":{"x":14036.230609316899,"y":19801.695537773197},"targetPosition":{"x":14104.32918427783,"y":19668.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3a6a9b74-37a9-48c4-956c-a6d6a5ae0080","savedPayload":{"position":{"x":14104.32918427783,"y":19668.044559144942},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"28f4f675-6764-4e30-b797-0ea44a6dfa53","savedPayload":{"position":{"x":14240.526334199694,"y":19400.742601888433},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Loop Code */\n\n/* Chaikin Oscillator\n\nKEY TAKEAWAYS\n- The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n- A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish.\n\n1. Money Flow Multiplier = [(Close - Low) - (High - Close)] / (High - Low) \n2. Money Flow Volume = Money Flow Multiplier x Volume for the Period\n3. ADL = Previous ADL + Current Period's Money Flow Volume\n4. Chaikin Oscillator = ('fast'-period EMA of ADL) - ('slow'-period EMA of ADL) */\n\n\nlet fastPeriod = 5 // Change value to set 'fast' period (must be less than or equal to 'fast')\nlet slowPeriod = 17 // Change value to set 'slow' period (must be greater than or equal to 'slow')\n\nlet candle = record.current\nlet volume = getElement('volumes', candle)\n\n\n// Set varibles\nvariable.totalVolume = volume.buy + volume.sell\t\nvariable.moneyFlowMultiplier = ((candle.close - candle.min) - (candle.max - candle.close)) / (candle.max - candle.min) \nvariable.moneyFlowVolume = variable.moneyFlowMultiplier * variable.totalVolume \nvariable.currentADL = variable.totalVolume + variable.moneyFlowVolume\nvariable.savedADL.push(variable.currentADL) // Push the currentADL into an array to be able to use \"previous ADL\"\n\nif (variable.savedADL.length > 2) { // Make sure we only save the current and previous\n variable.savedADL.splice(0, 1)\n}\n\n// Calculating the 'accDistLine' using previous ADL value if it is defined, else current\nif (variable.savedADL[0] === 'undefined')\n{variable.accDistLine = variable.savedADL[1] + variable.moneyFlowVolume} // Calculating with Current ADL\nelse\n{variable.accDistLine = variable.savedADL[0] + variable.moneyFlowVolume} // Calculating with Previous ADL\n\n\n// Calculate fastEMA and slowEMA of ADL\nif(isNaN(variable.previousEmaFast))\n{variable.previousEmaFast = variable.accDistLine}\nelse\n{variable.previousEmaFast}\n\nvariable.fastEMA = calculateEMAs(fastPeriod, variable.accDistLine, variable.previousEmaFast)\nvariable.previousEmaFast = variable.fastEMA\n\nif(isNaN(variable.previousEmaSlow))\n{variable.previousEmaSlow = variable.accDistLine}\nelse\n{variable.previousEmaSlow}\nvariable.slowEMA = calculateEMAs(slowPeriod, variable.accDistLine, variable.previousEmaSlow)\nvariable.previousEmaSlow = variable.slowEMA\n\n\n// Create EMA function for 'fast' and 'slow' ADL\nfunction calculateEMAs(periods, adl, previousEMA) {\n let k = 2 / (periods + 1)\n return adl * k + previousEMA * (1-k)\n}\n\n// Calculate Chaikin Oscillator value\nvariable.chaikinOscillator = variable.fastEMA - variable.slowEMA\n\n// Happy trading! CJ.","project":"Superalgos","id":"43f087d9-6da9-4387-a3ee-7e7e4ca247b3","savedPayload":{"position":{"x":13947.33381066081,"y":19411.075663396023},"targetPosition":{"x":13936.880964334045,"y":19311.623473859196},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2c6eff8c-0beb-4068-a9c6-26a06cbd242d","savedPayload":{"position":{"x":13936.880964334045,"y":19311.623473859196},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build arrays \n\nvariable.savedADL = []\n\n","project":"Superalgos","id":"67b6e8ff-b104-47c1-b8ec-a8847bce6b7a","savedPayload":{"position":{"x":13819.517534074947,"y":19390.831553964606},"targetPosition":{"x":13860.191198382527,"y":19299.477008200345},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c6684774-9a86-4b1b-a1ef-5ddd2027ae00","savedPayload":{"position":{"x":13860.191198382527,"y":19299.477008200345},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ba9d9a5f-61eb-49d8-a73d-15ca3e00ecd7","savedPayload":{"position":{"x":13921.201694843896,"y":19162.445189553953},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"31fee6c0-b932-4604-8a47-aa31fd679291","savedPayload":{"position":{"x":13968.132034355966,"y":18866.138687375413},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Chaikin Oscillator","id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae"}}}],"id":"f7bdd106-bdc2-4a99-8bce-173e94322727","savedPayload":{"position":{"x":13756.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Slow","project":"Superalgos","id":"4a233d99-e570-4936-a3f4-613c75213bc8","savedPayload":{"position":{"x":15567.729481237811,"y":17623.641979655422},"targetPosition":{"x":15625.963766385876,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c"}}}],"outputDatasetFolders":[],"id":"03c83aa5-5473-499d-8990-b99aa25cd543","savedPayload":{"position":{"x":15625.963766385876,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"af2be1a5-6589-49d4-8f89-8ae1cb3162f8","savedPayload":{"position":{"x":15686.182336682012,"y":17743.54743264471},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"ce465417-0658-430a-9888-2ffefee15357"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"24d1f7a4-66af-4169-a118-93618334f6ae","savedPayload":{"position":{"x":15771.549479256044,"y":17732.308635112942},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c541371a-27a9-436c-9342-081d67231318","savedPayload":{"position":{"x":15839.860194607763,"y":17784.725290570463},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"6f23340b-8d1f-4652-876f-4a70c3e21aec","savedPayload":{"position":{"x":15742.432336682012,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"ce465417-0658-430a-9888-2ffefee15357","savedPayload":{"position":{"x":16002.396103067893,"y":17740.110549951558},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"2597670e-3304-4839-ad6d-826290e3eabc","savedPayload":{"position":{"x":15901.531362448988,"y":18000.07431633744},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"96c24e28-6cd5-4d1f-9a35-35997b7e160a","savedPayload":{"position":{"x":15901.531362448988,"y":18116.542886633568},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0f2f6a8-0241-4aba-8751-a632e066d047","savedPayload":{"position":{"x":14118.132034355966,"y":18866.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Slow","project":"Superalgos","id":"1aedf3a0-5890-424e-a1f2-e54fc52659e1","savedPayload":{"position":{"x":16266.000000000002,"y":17597.08378961345},"targetPosition":{"x":16041.000000000002,"y":17986.79522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424"}}}],"outputDatasetFolders":[],"id":"d0cc5e79-a820-47d7-ad12-406b09b6f4dd","savedPayload":{"position":{"x":16041.000000000002,"y":17986.79522131645},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"fd87cb30-87eb-4ba7-9763-da651e48813c","savedPayload":{"position":{"x":16450.79899745976,"y":17774.10489744401},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3d36499e-ce24-4f0d-9875-48f7b63d05c8","savedPayload":{"position":{"x":16555.42711435863,"y":17868.31247704702},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"77a7753f-af11-40ac-a65d-ca75123b04ea","savedPayload":{"position":{"x":16625.822623626736,"y":17990.24107572407},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"6efb002f-6126-42ca-93fe-21c67f833c60","savedPayload":{"position":{"x":16655.094722342554,"y":18127.955472710124},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"b0367e88-7e82-42cd-944d-c4e9ca80d945","savedPayload":{"position":{"x":16205.711431703001,"y":18151.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08","savedPayload":{"position":{"x":16266.000000000002,"y":18376.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0b78bc25-8a2b-4a22-bcda-635f3b9b1187","savedPayload":{"position":{"x":16010.855715851498,"y":18489.00665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"4eec532d-30b6-4356-b69d-2460739799ce","savedPayload":{"position":{"x":15928.500000000002,"y":18571.362368870945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"160e01a5-da62-4b67-9042-68751949ee96","savedPayload":{"position":{"x":13986.330085889911,"y":19184.33673890936},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"singularVariableName\": \"slowARPS\",\n \"pluralVariableName\": \"slowARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c","savedPayload":{"position":{"x":13910.83713266845,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424","savedPayload":{"position":{"x":13760.83713266845,"y":19451.455642263958},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"9b3ec784-f875-4a31-9f2d-fdba3a4dd237","savedPayload":{"position":{"x":13968.132034355966,"y":20089.44374852799},"targetPosition":{"x":13725.426936043481,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"04be52be-03fa-4548-8ac1-11a688786301","savedPayload":{"position":{"x":13725.426936043481,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"be9d5502-b6ea-4109-931c-263e4ef39166","savedPayload":{"position":{"x":13835.392989106482,"y":20222.18279377747},"targetPosition":{"x":13659.057413418739,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d7f463c1-7208-4b96-8d46-893ee111e6f7","savedPayload":{"position":{"x":13659.057413418739,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"74a4a7e5-b4d5-46bd-9a3e-92c2705646cf","savedPayload":{"position":{"x":13621.779485199722,"y":20164.748029485323},"targetPosition":{"x":13575.426936043481,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3fe424b8-a927-4a4b-b82a-9fe013546966","savedPayload":{"position":{"x":13575.426936043481,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"735b28dc-532e-471f-bcdd-84ea80114a0e","savedPayload":{"position":{"x":13482.721837730996,"y":20186.772597152503},"targetPosition":{"x":13482.721837730996,"y":20036.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"86568b58-7899-4b50-80cd-4223c5b2a528","savedPayload":{"position":{"x":13482.721837730996,"y":20036.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"bf2645de-583b-4051-9f17-38935cb7d421","savedPayload":{"position":{"x":13343.66419026227,"y":20164.748029485323},"targetPosition":{"x":13390.016739418512,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e799bf00-cf17-4adb-92e9-d5c66bce7261","savedPayload":{"position":{"x":13390.016739418512,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"7c4af3a5-a3d3-4569-9074-6e5605f53cc2","savedPayload":{"position":{"x":13218.218474199382,"y":20100.83024462123},"targetPosition":{"x":13306.386262043254,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5d00b15c-7803-4044-8b44-166ea605e241","savedPayload":{"position":{"x":13306.386262043254,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"cde2b51c-7d16-4ee6-8b35-1dad3e18227f","savedPayload":{"position":{"x":13118.66419026227,"y":20001.275960684117},"targetPosition":{"x":13240.016739418512,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"af19875c-861c-407e-9275-8fb2111277dc","savedPayload":{"position":{"x":13240.016739418512,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"da247784-c47c-41ae-b764-519d47700a50","savedPayload":{"position":{"x":13054.746405398178,"y":19875.83024462123},"targetPosition":{"x":13197.404882842451,"y":19829.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"56774359-2338-4b22-bf66-26835a7f1266","savedPayload":{"position":{"x":13197.404882842451,"y":19829.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"79052dd4-e79c-4139-b034-a2b59a7cad5f","savedPayload":{"position":{"x":13032.721837730996,"y":19736.772597152503},"targetPosition":{"x":13182.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"30c88625-0df0-4647-9ebf-51a5ef868f58","savedPayload":{"position":{"x":13182.721837730996,"y":19736.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8b9a90a7-170a-4f59-8132-bd890aab9a26","savedPayload":{"position":{"x":13482.721837730996,"y":19736.772597152503},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 17 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ. :-)","project":"Superalgos","id":"adea7d76-a792-4556-b017-093de9fe2b0f","savedPayload":{"position":{"x":13268.09683828102,"y":19536.760753427396},"targetPosition":{"x":13331.028877386005,"y":19459.0461572817},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a6150e04-c314-489d-824f-23afa0072a7e","savedPayload":{"position":{"x":13331.028877386005,"y":19459.0461572817},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"cc836ccb-c2dc-4ba5-9fcd-080a69c50b8a","savedPayload":{"position":{"x":13192.03182941918,"y":19432.066250449483},"targetPosition":{"x":13285.389872068901,"y":19396.22945549495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"679b4d08-204b-4564-9324-19f7ed005c08","savedPayload":{"position":{"x":13285.389872068901,"y":19396.22945549495},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ab30d1a8-1659-46d7-9620-b2783b58feef","savedPayload":{"position":{"x":13425.426936043481,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e34788bb-3c57-4a14-abb5-451f35533e49","savedPayload":{"position":{"x":13668.132034355966,"y":19166.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Slow","id":"e12e90bd-bc37-42da-9f83-7b1506391bd9"}}}],"id":"81becef8-2376-47a7-8cdf-a559c45ed950","savedPayload":{"position":{"x":13668.132034355966,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Fast","project":"Superalgos","id":"a4be096d-4fa4-44ba-983d-af202af96d7d","savedPayload":{"position":{"x":16144.729481237811,"y":17296.141979655422},"targetPosition":{"x":16202.96376638588,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"08336286-f6f1-4fa5-ba1e-912897063979"}}}],"outputDatasetFolders":[],"id":"0727df65-0f8c-4415-a85f-d9e322240273","savedPayload":{"position":{"x":16202.96376638588,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"5790535f-17f2-4ee0-bded-368ebd9489dc","savedPayload":{"position":{"x":16263.182336682012,"y":17416.04743264471},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"ee739a5f-2a9e-40d4-a557-8cb53521d7e3","savedPayload":{"position":{"x":16348.549479256048,"y":17404.808635112942},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c926b53f-07cb-4d2c-8260-9dadc6bb2f1b","savedPayload":{"position":{"x":16416.86019460776,"y":17457.225290570463},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"73f3249b-2f51-4399-950d-186d6d68c78e","savedPayload":{"position":{"x":16319.432336682012,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1","savedPayload":{"position":{"x":16579.39610306789,"y":17412.610549951558},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"9261d5a5-4da2-4119-a78a-7d231491c2ee","savedPayload":{"position":{"x":16478.531362448986,"y":17672.57431633744},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"68b54ef4-857f-4a75-88ea-319ba92f5fd9","savedPayload":{"position":{"x":16478.531362448986,"y":17789.042886633568},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b138ab56-8d61-44f0-b0e9-27f171bbbfbe","savedPayload":{"position":{"x":13774.198051533947,"y":19272.204704553395},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Fast","project":"Superalgos","id":"f679b2a9-f5ce-46fb-852e-be58c502a0da","savedPayload":{"position":{"x":16843,"y":17269.58378961345},"targetPosition":{"x":16618,"y":17659.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9"}}}],"outputDatasetFolders":[],"id":"d4701ed1-5658-45b5-8835-14f1414491f3","savedPayload":{"position":{"x":16618,"y":17659.29522131645},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"258d211e-d162-4064-ab04-a6f36ae306e6","savedPayload":{"position":{"x":17027.79899745976,"y":17446.60489744401},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"82262685-1d6f-4c35-8584-3f13ad1b0921","savedPayload":{"position":{"x":17132.427114358637,"y":17540.81247704702},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"c7c3c7a8-4fb5-45f2-bb11-51d6cfdfda3e","savedPayload":{"position":{"x":17202.822623626736,"y":17662.74107572407},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"0f0a43f4-60d2-42fa-93fa-be2e21f8c302","savedPayload":{"position":{"x":17232.094722342554,"y":17800.455472710124},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"d29fbaa9-5eb9-4cb0-94e3-3ea6d18f20c2","savedPayload":{"position":{"x":16782.711431703,"y":17824.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf","savedPayload":{"position":{"x":16843,"y":18049.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0394d6ce-4648-4295-aa21-431adf475fe3","savedPayload":{"position":{"x":16587.855715851503,"y":18161.50665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"c90561ab-2b37-4df4-8f06-10e06ed4edee","savedPayload":{"position":{"x":16505.5,"y":18243.862368870945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"8634ce99-462c-4cf4-b55a-e939bd458a6b","savedPayload":{"position":{"x":13456.000000000002,"y":19404.00665301945},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Fast","config":"{\n \"codeName\": \"fastARPS\",\n \"singularVariableName\": \"fastARPS\",\n \"pluralVariableName\": \"fastARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"08336286-f6f1-4fa5-ba1e-912897063979","savedPayload":{"position":{"x":13290.798305156108,"y":19462.445189553953},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9","savedPayload":{"position":{"x":13107.670815722175,"y":19433.440644631923},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"aa7ec15b-6515-41b2-bcf8-caf282254a2f","savedPayload":{"position":{"x":17020.13933855677,"y":18701.881922864293},"targetPosition":{"x":16723.832836378235,"y":18748.81226237636},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0bdacd74-1544-46ef-80b8-c36764f748f1","savedPayload":{"position":{"x":16723.832836378235,"y":18748.81226237636},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"6ba23d0d-4820-44d9-882e-12b53e3340c5","savedPayload":{"position":{"x":17020.13933855677,"y":18889.60328091257},"targetPosition":{"x":16723.832836378235,"y":18842.672941400506},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0fd74c82-d165-42ba-a60e-2557ef8f7469","savedPayload":{"position":{"x":16723.832836378235,"y":18842.672941400506},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"3548eb27-ca3d-4b56-851d-815322a07af3","savedPayload":{"position":{"x":16828.479270084455,"y":19000.038326771228},"targetPosition":{"x":16694.8282914562,"y":18931.939751810296},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"70fe36c1-0c68-49e7-a2fa-8f60232ff4ef","savedPayload":{"position":{"x":16694.8282914562,"y":18931.939751810296},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"1473d657-276b-406b-90e6-a66131604ff6","savedPayload":{"position":{"x":16745.724385733636,"y":19113.940653422378},"targetPosition":{"x":16639.658368555654,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"571474ac-c4ed-4ee7-af2c-e4a56098cfad","savedPayload":{"position":{"x":16639.658368555654,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"0b9787b0-9547-4688-be4a-48a727f42e04","savedPayload":{"position":{"x":16631.822059082486,"y":19196.695537773197},"targetPosition":{"x":16563.723484121554,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e255bc82-518f-41e0-b9c5-dc573217cfb9","savedPayload":{"position":{"x":16563.723484121554,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"8e31b59b-6550-469d-a818-edb4b9eda503","savedPayload":{"position":{"x":16497.921843467797,"y":19240.20235515624},"targetPosition":{"x":16474.456673711764,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"4c52fc87-fac3-4a74-928c-beff9640f538","savedPayload":{"position":{"x":16474.456673711764,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"47dd70e8-0226-4bda-835d-8b426fc2e23d","savedPayload":{"position":{"x":16357.13082493159,"y":19240.20235515624},"targetPosition":{"x":16380.595994687626,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ce61113d-7b92-454d-9d22-557fb0532385","savedPayload":{"position":{"x":16380.595994687626,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"c456e845-561a-4761-b7d8-0424bdd76729","savedPayload":{"position":{"x":16223.230609316897,"y":19196.695537773197},"targetPosition":{"x":16291.329184277829,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b2f7070c-8430-4a3b-9477-b71fa1215cdb","savedPayload":{"position":{"x":16291.329184277829,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"231fd372-de75-42b8-827b-7a315ac96a7f","savedPayload":{"position":{"x":16109.328282665747,"y":19113.940653422378},"targetPosition":{"x":16215.394299843729,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ba0880ca-226d-4e4c-a2d6-620d6dc5cfe0","savedPayload":{"position":{"x":16215.394299843729,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"867c1562-64d7-47d1-ab5b-6de88bc115dd","savedPayload":{"position":{"x":12709.264051131018,"y":19438.53298721914},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 3 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ! :-)","project":"Superalgos","id":"35a38ab1-ff66-4072-b82f-6cc2f56ff6f4","savedPayload":{"position":{"x":12698.93098962343,"y":19145.34046368026},"targetPosition":{"x":12798.383179160257,"y":19134.88761735349},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"77b480da-70d7-43ab-bd51-98044b9350be","savedPayload":{"position":{"x":12798.383179160257,"y":19134.88761735349},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"8b82130d-b51f-410c-82b3-34abb02bc3a4","savedPayload":{"position":{"x":12719.175099054848,"y":19017.524187094394},"targetPosition":{"x":12810.529644819107,"y":19058.197851401972},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e1fcfd73-c477-4574-986f-85583fa489af","savedPayload":{"position":{"x":12810.529644819107,"y":19058.197851401972},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"19eacb84-6904-4b79-aa5c-7f6c69c89b04","savedPayload":{"position":{"x":12947.561463465498,"y":19119.208347863343},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b099e79b-ee47-4937-bf88-43f1a4f55a8c","savedPayload":{"position":{"x":13243.867965644038,"y":19166.138687375413},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Fast","id":"fdffbdff-a42f-47db-b068-4a711070bef3"}}}],"id":"b1eaf829-987d-4ddc-92c7-10edb3e0d194","savedPayload":{"position":{"x":13456.000000000002,"y":18954.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Average VS Average","project":"Superalgos","id":"2edf9e6c-e713-45fc-9764-73f1465f1352","savedPayload":{"position":{"x":13298.615075075051,"y":18964.99615794743},"targetPosition":{"x":13123.757233747232,"y":18823.399069961215},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15"}}}],"outputDatasetFolders":[],"id":"322cf5e8-7f9d-4bdd-abed-5f78672b93a9","savedPayload":{"position":{"x":13123.757233747232,"y":18823.399069961215},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"87830a28-1634-48f8-a226-506c89ade476","savedPayload":{"position":{"x":13138.198836524625,"y":18920.974720510905},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3ab9def4-53a1-458f-83d7-b3be09887d4e","savedPayload":{"position":{"x":13100.330725060212,"y":18979.28649860078},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"78ca9971-aa46-458f-b8d9-354426317bd4","savedPayload":{"position":{"x":13035.419976144436,"y":19004.20340059676},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"f51ac085-64ae-45c2-9467-e98eb801379d","savedPayload":{"position":{"x":12968.260289627915,"y":18986.208016830733},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"85b582f1-7cc2-4535-ac54-7df234e3db4f","savedPayload":{"position":{"x":13029.532181067105,"y":18891.857577936873},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8","savedPayload":{"position":{"x":12878.503883151308,"y":19126.26173524281},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"885a6862-324a-4528-b842-8c40f0aafc97","savedPayload":{"position":{"x":12807.3023044332,"y":18856.659823302816},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"bf186655-c6bd-487d-ab02-65b7535b80b1","savedPayload":{"position":{"x":12738.843796457542,"y":18762.434770622694},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f8c12a67-d98f-4a20-9f95-5e590321403f","savedPayload":{"position":{"x":13243.867965644038,"y":19316.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Average VS Average","project":"Superalgos","id":"3d362705-7d3b-4205-af78-6aeeccd326b9","savedPayload":{"position":{"x":12749.31287115968,"y":19396.915298070246},"targetPosition":{"x":12702.275062689236,"y":18949.380445154526},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c"}}}],"outputDatasetFolders":[],"id":"41ea773f-0b13-4691-8393-f562352f89ee","savedPayload":{"position":{"x":12702.275062689236,"y":18949.380445154526},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"627ead20-a71e-47c1-8d5d-42506ab2433d","savedPayload":{"position":{"x":12519.243573305126,"y":19360.475901093694},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"de6cab83-afd5-4f5a-ad2e-1cf0fc07b7e8","savedPayload":{"position":{"x":12401.810255566577,"y":19357.400801445783},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"f0dea610-c1c0-4f2f-9d79-8e2cfc90b582","savedPayload":{"position":{"x":12289.174275450572,"y":19324.036504117143},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"f54e9145-daed-48a1-a2bb-ce82ceec4b78","savedPayload":{"position":{"x":12189.011588862255,"y":19262.656730833613},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"947c751a-393b-4499-88d0-54d112a2d923","savedPayload":{"position":{"x":12108.148117365956,"y":19177.444411709588},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"03d0b6f4-795f-43f9-aed7-398ff9be2c31","savedPayload":{"position":{"x":12472.205764834682,"y":18912.941048177974},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec","savedPayload":{"position":{"x":12291.179606750065,"y":18766.34895577042},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"b7661232-5ecd-42e5-b4e2-0387253c51cc","savedPayload":{"position":{"x":12431.46982776093,"y":18525.364496474027},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"25b50fcf-ad3c-436c-90b4-9b83dfafd4fb","savedPayload":{"position":{"x":12449.689526249205,"y":18410.32984754675},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"90fe53a1-9c47-4b05-af43-8876c468d379","savedPayload":{"position":{"x":12925.669914110093,"y":19184.33673890936},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"singularVariableName\": \"averageVsAverage\",\n \"pluralVariableName\": \"averageVsAverages\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15","savedPayload":{"position":{"x":12767.532389956295,"y":19108.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c","savedPayload":{"position":{"x":12658.551010755493,"y":18958.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"abf7c3f9-418d-44be-9d5f-68117e6e26cf","savedPayload":{"position":{"x":11465.997291705151,"y":19436.727492435068},"targetPosition":{"x":11890.26136041708,"y":19012.46342372314},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"fc0364a2-a5b0-4f77-81cb-448f3a532efb","savedPayload":{"position":{"x":11958.596466474826,"y":19114.405409046878},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"615b00d5-f0e5-48e4-883f-8985b00b7470","savedPayload":{"position":{"x":11245.31760010297,"y":19132.987954698667},"targetPosition":{"x":11779.92151461599,"y":18860.59365485494},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"20fcfc66-d336-4c0d-872f-50a5d8cd50b6","savedPayload":{"position":{"x":11811.493133483104,"y":18891.553385199248},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"bullPriceDeviation","config":"{\n \"codeName\": \"bullPriceDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.bullPriceDeviation)) {\nvariable.bullPriceDeviation\n}\nelse {\nvariable.bullPriceDeviation = 1\n}","project":"Superalgos","id":"fa9aa35e-98af-416d-b3b9-395327e5cd9d","savedPayload":{"position":{"x":11925.045623569087,"y":18640.3908017439},"targetPosition":{"x":12074.441767668373,"y":18653.836698079413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7bd05b9a-a315-4e3d-93b0-3943a7f3ba50","savedPayload":{"position":{"x":12074.441767668373,"y":18653.836698079413},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"smaPrice","config":"{\n \"codeName\": \"smaPrice\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.smaPrice)) {\nvariable.smaPrice\n}\nelse {\nvariable.smaPrice = 1\n}","project":"Superalgos","id":"63142088-1b62-4a15-985f-c53cd6adb314","savedPayload":{"position":{"x":11986.932098746105,"y":18449.923815917784},"targetPosition":{"x":12115.699417786385,"y":18526.85870752867},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"67b38c00-0e3d-47bc-942c-0fdda9625e9a","savedPayload":{"position":{"x":12115.699417786385,"y":18526.85870752867},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"volumeDeviation","config":"{\n \"codeName\": \"volumeDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.volumeDeviation)) {\nvariable.volumeDeviation\n}\nelse {\nvariable.volumeDeviation = 1\n}","project":"Superalgos","id":"6ec8c68a-20f5-4d3d-8ef5-1c0e87f0c5a3","savedPayload":{"position":{"x":12125.3304142135,"y":18305.170526575857},"targetPosition":{"x":12207.964961431315,"y":18430.35651463405},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"aa0f2fc4-d1de-49d8-87cb-d2d68b4bbb09","savedPayload":{"position":{"x":12207.964961431315,"y":18430.35651463405},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"openInterestDeviation","config":"{\n \"codeName\": \"openInterestDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.openInterestDeviation)) {\nvariable.openInterestDeviation\n}\nelse {\nvariable.openInterestDeviation = 1\n}","project":"Superalgos","id":"3fde42f1-88e4-4a07-9f0d-ad1ceef8ae89","savedPayload":{"position":{"x":12312.829086249,"y":18234.80109795487},"targetPosition":{"x":12332.964076121649,"y":18383.44356222006},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"264be2f7-a27c-414b-8aee-7473c120b89f","savedPayload":{"position":{"x":12332.964076121649,"y":18383.44356222006},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"536bed44-cdea-4518-974c-4fbd6787c969","savedPayload":{"position":{"x":12373.234055866946,"y":18680.728490750444},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"EDIT TOP LINES HERE TO CHANGE PERIODS","code":"// The Average VS Average Oscillator\n\n/* The Average VS Average Oscillator can be used to recognize changes between a fast average ('fastPeriod') and a slow average ('slowPeriod'). It measures 'Price Action', 'Volume', and a so called 'Open Interest'.\n'Bull Price Action' and 'Bear Price Action' is defined by the amount between the candle close and max and min.\n'Bull Volume' and 'Bear Volume' is divided using the price action.\n'Open Interest' is based upon the statement where:\nBull Candle and Volume Increase = Bull Interest\nBull Candle and Volume Decrease = Bear Interest\nBear Candle and Volume Increase = Bear Interest\nBear Candle and Volume Decrease = Bull Interest */\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n/* USER DEFINED VALUES SECTION */\n\nlet fastPeriod = 5 // Change this number to the period of your choice (must be less than 'slowPeriod')\nlet slowPeriod = 21 // Change this number to the period of your choice (must be greater than 'fastPeriod')\nlet periodMultiplier = 3 // The 'slowPeriod' is muliplied by the 'periodMultiplier to create the \"long term\" trend\nlet fastBoost = 1.00 // '1.00' equals 'no extra boost' to your 'fastPeriod' where as '1.23' would boost the value by 23%\nlet gravity = 0 // '0' equals 'no gravity' (pullback towards midline ('slowPeriod'))\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring variables used\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \nlet volCandle = record.current\nlet volume = getElement('volumes', volCandle)\nlet totalVolume = volume.buy + volume.sell\nlet totalRange = candle.max - candle.min\nlet multipliedFast = fastPeriod * periodMultiplier\nlet multipliedSlow = slowPeriod * periodMultiplier\n\nif ( candle.close > candle.open ) { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\nelse { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Volume Difference'\n\nvariable.previousCurrentVolume.push(totalVolume)\nif (variable.previousCurrentVolume.length > 2) {\n variable.previousCurrentVolume.splice(0, 1)\n}\n\nif (variable.previousCurrentVolume[1] === 'undefined') {\n variable.positiveVolumeDifference = 0.01\n}\nelse {\n if (variable.previousCurrentVolume[variable.previousCurrentVolume.max] > variable.previousCurrentVolume[0]) {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[1] - variable.previousCurrentVolume[0]) \n }\n else {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[0] - variable.previousCurrentVolume[1])\n }\n}\n\nvariable.bullVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bullPriceRange / totalRange)\nvariable.bearVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bearPriceRange / totalRange)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Open Interest'\n// Converting values to percentages due to the differences of range and volume (range might be in decimals while volume often is in thousands)\n\nif ( candle.close > candle.open && variable.previousCurrentVolume[1] > variable.previousCurrentVolume[0] ) { // Candle UP & Volume UP, Bullish Interest\n variable.openInterest = 1 + ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close < candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle DOWN & Volume DOWN, Bullish Interest\n variable.openInterest = 1 + ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close > candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle UP & Volume DOWN, Bearish Interest\n variable.openInterest = 1 - ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse { // Candle DOWN & Volume UP, Bearish Interest\n variable.openInterest = 1 - ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Saving to arrays\n\nvariable.savedCandleClose.push(candle.close)\nif (variable.savedCandleClose.length > multipliedSlow) {\n variable.savedCandleClose.splice(0, 1)\n}\n\nvariable.savedTotalRange.push(totalRange)\nif (variable.savedTotalRange.length > multipliedSlow) {\n variable.savedTotalRange.splice(0, 1)\n}\n\nvariable.savedBullPriceRange.push(variable.bullPriceRange)\nif (variable.savedBullPriceRange.length > multipliedSlow) {\n variable.savedBullPriceRange.splice(0, 1)\n}\n\nvariable.savedTotalVolume.push(totalVolume)\nif (variable.savedTotalVolume.length > multipliedSlow) {\n variable.savedTotalVolume.splice(0, 1)\n}\n\nvariable.savedOpenInterest.push(variable.openInterest)\nif (variable.savedOpenInterest.length > multipliedSlow) {\n variable.savedOpenInterest.splice(0, 1)\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Calling SMA functions\n\nvariable.smaMultipliedFastCandleClose = calculateSMA(variable.savedCandleClose, multipliedFast)\nvariable.smaSlowCandleClose = calculateSMA(variable.savedCandleClose, slowPeriod)\nvariable.smaLongTermCandleClose = calculateSMA(variable.savedCandleClose, multipliedSlow)\n\nvariable.smaFastTotalRange = calculateSMA(variable.savedTotalRange, fastPeriod)\nvariable.smaSlowTotalRange = calculateSMA(variable.savedTotalRange, slowPeriod)\nvariable.smaLongTermRange = calculateSMA(variable.savedTotalRange, multipliedSlow)\n\nvariable.smaFastBullPriceRange = calculateSMA(variable.savedBullPriceRange, fastPeriod)\nvariable.smaSlowBullPriceRange = calculateSMA(variable.savedBullPriceRange, slowPeriod)\n\nvariable.smaFastTotalVolume = calculateSMA(variable.savedTotalVolume, fastPeriod)\nvariable.smaLongTermTotalVolume = calculateSMA(variable.savedTotalVolume, multipliedSlow)\n\nvariable.smaFastOpenInterest = calculateSMA(variable.savedOpenInterest, fastPeriod)\nvariable.smaSlowOpenInterest = calculateSMA(variable.savedOpenInterest, slowPeriod)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Creating the SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calculation\n if (src.length < periods) { return 0 }\n \n // Initialize sum variable\n let sum = 0 \n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring record variables by comparing 'fastPeriod' values with 'slowPeriod' values, also applying 'fastBoost' and 'gravity'\n\nvariable.fastPriceRange = variable.smaFastTotalRange\nvariable.slowPriceRange = variable.smaSlowTotalRange\nvariable.longTermPriceRange = variable.smaLongTermRange\n\nvariable.bullPriceDeviation = ((((variable.smaFastBullPriceRange * fastBoost) + (variable.smaSlowBullPriceRange * gravity)) / (gravity + 1)) / variable.slowPriceRange) * 2\n\nvariable.volumeDeviation = variable.smaFastTotalVolume / variable.smaLongTermTotalVolume\n\nvariable.openInterestDeviation = ((((variable.smaFastOpenInterest * fastBoost) + (variable.smaSlowOpenInterest * gravity)) / (gravity + 1)) / variable.smaSlowOpenInterest)\n\nvariable.smaPrice = variable.smaMultipliedFastCandleClose / variable.smaLongTermCandleClose\n\n// Happy trading! CJ.","project":"Superalgos","id":"8c60ba71-a9d3-4f8e-afe0-896444288364","savedPayload":{"position":{"x":12573.245899592053,"y":18466.10349130047},"targetPosition":{"x":12650.96049573775,"y":18529.035530405454},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a063882c-12d0-4d12-9b5a-ca5b1db72b7f","savedPayload":{"position":{"x":12650.96049573775,"y":18529.035530405454},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 6 arrays \n\nvariable.previousCurrentVolume = []\nvariable.savedTotalRange = []\nvariable.savedBullPriceRange = [] \nvariable.savedTotalVolume = [] \nvariable.savedOpenInterest = [] \nvariable.savedCandleClose = [] ","project":"Superalgos","id":"34d8c2bd-b8fc-4584-9d03-262c2ed57243","savedPayload":{"position":{"x":12677.94040256997,"y":18390.038482438627},"targetPosition":{"x":12713.7771975245,"y":18483.39652508835},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7aab7dde-e3ed-45b0-907e-f7e7ca67c900","savedPayload":{"position":{"x":12713.7771975245,"y":18483.39652508835},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"59f62f92-018d-4f53-9c86-efa887cad1ce","savedPayload":{"position":{"x":12767.532389956295,"y":18623.43358906293},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"331e099d-5ffe-4d60-8186-effe0aef5d17","savedPayload":{"position":{"x":12943.867965644038,"y":18866.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Average VS Average","id":"13acaaae-6a8e-4e48-a326-9d209079629f"}}}],"id":"01b8702d-ee62-45f7-ac01-e1f7ce70c843","savedPayload":{"position":{"x":13243.867965644038,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"plotters":[{"type":"Plotter","name":"Chaikin Oscillator Plotter","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.zeroLine","project":"Superalgos","id":"80862799-63a8-4ba6-a807-b8425ebf42e6","savedPayload":{"position":{"x":12437.728644668177,"y":19458.751691732494},"targetPosition":{"x":12390.798305156108,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ef40ac92-9977-4887-9c81-b2442254f267","savedPayload":{"position":{"x":12390.798305156108,"y":19162.445189553953},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.zeroLine","project":"Superalgos","id":"926f7d83-fec5-4224-b5a4-8e1a54520950","savedPayload":{"position":{"x":12071.473665800311,"y":19400.742601888433},"targetPosition":{"x":12207.670815722175,"y":19133.440644631923},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47","savedPayload":{"position":{"x":12207.670815722175,"y":19133.440644631923},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.chaikinOscillator","project":"Superalgos","id":"e741c1f0-43b2-4863-8d93-7fc46b343d93","savedPayload":{"position":{"x":11809.264051131018,"y":19138.53298721914},"targetPosition":{"x":12076.566008387528,"y":19002.335837297276},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"53915588-afe8-48a8-9d68-5726ff873676","savedPayload":{"position":{"x":12076.566008387528,"y":19002.335837297276},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.chaikinOscillator","project":"Superalgos","id":"10fc95bd-dc19-407a-809e-6f4f385316f6","savedPayload":{"position":{"x":11751.254961286957,"y":18772.278008351273},"targetPosition":{"x":12047.561463465498,"y":18819.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8","savedPayload":{"position":{"x":12047.561463465498,"y":18819.208347863343},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b2a71e98-e51b-4b89-972e-d5581f4625e0","savedPayload":{"position":{"x":12343.867965644038,"y":18866.138687375413},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"246dfad4-544c-47fb-8b84-977bdd41cd47","savedPayload":{"position":{"x":14463.44450422656,"y":16854.484741416603},"targetPosition":{"x":14753.22225211328,"y":16932.13045494736},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8896e73d-ee20-461b-9608-55f4927c4b10","savedPayload":{"position":{"x":14753.22225211328,"y":16932.13045494736},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"163aeab0-ae3e-4467-9da4-9f96dc09ec0f","savedPayload":{"position":{"x":14893.000000000002,"y":16749.968547342785},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"ef40ac92-9977-4887-9c81-b2442254f267"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"e1f60b5e-6727-44d7-8e9c-d913098cd747","savedPayload":{"position":{"x":15120.64571353076,"y":16719.998420591397},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47"}}}],"id":"f79ac980-28be-4eaf-87ee-0ae394c976eb","savedPayload":{"position":{"x":12256.000000000002,"y":18654.00665301945},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"Chaikin Oscillator","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"60001259-de7c-4c30-b752-839c3ec0cd10","savedPayload":{"position":{"x":11743.867965644038,"y":18441.874618663485},"targetPosition":{"x":12043.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7dcea241-9bf6-4dcd-99d5-f568e8ebd151","savedPayload":{"position":{"x":12043.867965644038,"y":18441.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Chaikin Oscillator Begin","project":"Superalgos","id":"9efb3b5e-4eeb-4aa8-a18e-bada560c738f","savedPayload":{"position":{"x":12131.735931288074,"y":18229.74258430752},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator Begin","id":"53915588-afe8-48a8-9d68-5726ff873676"}}},{"type":"Polygon Vertex","name":"Chaikin Oscillator End","project":"Superalgos","id":"08067dd0-d1a3-4b75-bcee-996118cfd9db","savedPayload":{"position":{"x":12343.867965644038,"y":18141.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator End","id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8"}}}],"id":"b5dd57fb-a9cc-48f2-bc06-cb3b02544f08","savedPayload":{"position":{"x":12343.867965644038,"y":18441.874618663485},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"d4571993-801c-4a30-9fc9-eac333de1451","savedPayload":{"position":{"x":12556.000000000002,"y":18654.00665301945},"targetPosition":{"x":12856.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae","savedPayload":{"position":{"x":12856.000000000002,"y":18654.00665301945},"targetPosition":{"x":13156.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"9639a20f-b875-46f6-8cbb-4e71cc941041","savedPayload":{"position":{"x":13156.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Slow Plotter","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"a210d685-38e1-43a3-9878-adbd61c761e0","savedPayload":{"position":{"x":15538.752452292845,"y":18825.3271911492},"targetPosition":{"x":15238.886722607795,"y":18816.35255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e","savedPayload":{"position":{"x":15238.886722607795,"y":18816.35255129838},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"b884cd0e-265e-4f70-846f-33a37a257ecc","savedPayload":{"position":{"x":15471.572466325475,"y":19083.76338171794},"targetPosition":{"x":15205.296729624106,"y":18945.57064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5","savedPayload":{"position":{"x":15205.296729624106,"y":18945.57064658275},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"eb99829a-5d1a-40e4-9ccc-7fc73d6c6948","savedPayload":{"position":{"x":15298.914129735489,"y":19287.45804025429},"targetPosition":{"x":15118.967561329113,"y":19047.417975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2852ef63-8ffe-4516-b5f9-f635ea773efa","savedPayload":{"position":{"x":15118.967561329113,"y":19047.417975850924},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"8aedf7aa-675e-467b-b9b5-d60754399725","savedPayload":{"position":{"x":15054.974543600074,"y":19396.066941484063},"targetPosition":{"x":14996.997768261406,"y":19101.72242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"66be2c9a-b271-4410-b305-d6ff7a8f6806","savedPayload":{"position":{"x":14996.997768261406,"y":19101.72242646581},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"4db679ee-e6b7-43e0-89b9-df275970ab75","savedPayload":{"position":{"x":14788.068934676035,"y":19388.07876051796},"targetPosition":{"x":14863.544963799388,"y":19097.728335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31","savedPayload":{"position":{"x":14863.544963799388,"y":19097.728335982767},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"f68cafa6-18dd-40b8-b669-265897ffbbc7","savedPayload":{"position":{"x":14551.061232193262,"y":19265.075654564916},"targetPosition":{"x":14745.041112558001,"y":19036.226783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e","savedPayload":{"position":{"x":14745.041112558001,"y":19036.226783006245},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"0fbe8beb-9d62-46b2-9d77-9b246aff6bdc","savedPayload":{"position":{"x":12634.447798537763,"y":18587.46242578744},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95265ad5-3c49-4d1f-9a60-01bcdf2816be","savedPayload":{"position":{"x":15081.40991376369,"y":19329.96089514218},"targetPosition":{"x":14918.01820325918,"y":19078.359724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d3facbf8-a2e6-4452-b21b-35352511a827","savedPayload":{"position":{"x":14918.01820325918,"y":19078.359724758553},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"36c97105-26c3-475e-949d-ce8c3480f651","savedPayload":{"position":{"x":14692.252985509345,"y":19120.202834595064},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"6dd790c5-abf3-4fb3-b19f-6afaf91da40a","savedPayload":{"position":{"x":14503.025322371046,"y":18990.15026487943},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5"}}}],"id":"c92be7eb-fddc-4bc6-a65d-a0a40bc37ec8","savedPayload":{"position":{"x":12490.357013017727,"y":18470.780008342786},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95ed4962-8fe8-4f35-ae47-64204481b727","savedPayload":{"position":{"x":14562.654978611015,"y":19333.231176915182},"targetPosition":{"x":14578.355765483899,"y":19033.642316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"e7445d37-5968-48de-927c-4efdb45b7c59","savedPayload":{"position":{"x":14578.355765483899,"y":19033.642316488807},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"0f784377-cb5c-4f2f-96b3-68407b05af78","savedPayload":{"position":{"x":14371.113104713564,"y":18934.7926379701},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"2852ef63-8ffe-4516-b5f9-f635ea773efa"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"8c0f843b-249e-4a35-88b9-70f63e1890c3","savedPayload":{"position":{"x":14294.46769193041,"y":18718.352669189557},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"66be2c9a-b271-4410-b305-d6ff7a8f6806"}}}],"id":"f019e42a-3005-4a2b-9717-48d6902c03da","savedPayload":{"position":{"x":12442.36932297498,"y":18291.687510965396},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"b3ea885c-fc4e-44b5-93e4-c965b7622d6d","savedPayload":{"position":{"x":14141.051196759618,"y":19030.96039000926},"targetPosition":{"x":14329.847314074568,"y":18797.81660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"a1fa021f-4b0f-41ee-a344-cdb8360b641a","savedPayload":{"position":{"x":14329.847314074568,"y":18797.81660157217},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"1c703412-aa66-4f3c-953e-f1798935a713","savedPayload":{"position":{"x":14220.286862779038,"y":18596.031352115377},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"e915dba3-f07e-42df-9705-7da67057decd","savedPayload":{"position":{"x":14285.499642952427,"y":18375.876695820127},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e"}}}],"id":"07d9669b-ce23-49fb-b2dd-666c5f32c755","savedPayload":{"position":{"x":12508.814394964262,"y":18118.592180523327},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"59717ffa-8d07-4e2b-98da-e6fb3353ea04","savedPayload":{"position":{"x":12741.958183401353,"y":18307.38829783828},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"6f7acaa5-1243-4f77-875f-5397475358e9","savedPayload":{"position":{"x":12699.574023683499,"y":17530.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c1de33b9-fa92-419f-baa8-081dc437c569","savedPayload":{"position":{"x":12959.38164481883,"y":17380.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8fd22998-6471-490b-bd96-9d30d99978b8","savedPayload":{"position":{"x":12959.38164481883,"y":17680.157215285468},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"20fc3099-2c91-4c55-9336-60553f207253","savedPayload":{"position":{"x":13109.38164481883,"y":17360.40934064736},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"6906425e-38ab-4aaa-84da-b4e43eda38cd","savedPayload":{"position":{"x":13399.15939270555,"y":17438.055054178116},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b9bd72d6-fe20-411e-a481-3593020f9ee2","savedPayload":{"position":{"x":13187.027358349585,"y":17650.18708853408},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"457c2cc9-cf06-407d-a12b-e9a24ce43a3b","savedPayload":{"position":{"x":13519.18926595416,"y":17530.157215285468},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"8d54d8bf-89eb-41f8-bfb2-8a471506b3b5","savedPayload":{"position":{"x":13669.18926595416,"y":17789.9648364208},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2731ea97-36e9-4bad-8339-803c567e8a87","savedPayload":{"position":{"x":13369.18926595416,"y":17789.9648364208},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"75e49a63-45a5-4f16-876e-53a509ddb245","savedPayload":{"position":{"x":13109.38164481883,"y":17939.9648364208},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e12e90bd-bc37-42da-9f83-7b1506391bd9","savedPayload":{"position":{"x":13031.735931288074,"y":18229.74258430752},"targetPosition":{"x":13243.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f3a68e45-18b6-4192-bccd-00364c5d72c0","savedPayload":{"position":{"x":13243.867965644038,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Fast Plotter","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"7f32a7cc-bbbb-4b76-918d-fb4b49ae1cbe","savedPayload":{"position":{"x":15614.752452292845,"y":18600.8271911492},"targetPosition":{"x":15314.886722607795,"y":18591.85255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"43c595ce-8ba1-4a6a-b126-38898e46c880","savedPayload":{"position":{"x":15314.886722607795,"y":18591.85255129838},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"17b6dd00-6205-482f-8ed4-1c7b215aa634","savedPayload":{"position":{"x":15547.572466325475,"y":18859.26338171794},"targetPosition":{"x":15281.296729624106,"y":18721.07064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d","savedPayload":{"position":{"x":15281.296729624106,"y":18721.07064658275},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"c65449b6-1047-449c-8974-d439b263f767","savedPayload":{"position":{"x":15374.914129735489,"y":19062.95804025429},"targetPosition":{"x":15194.967561329117,"y":18822.917975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade","savedPayload":{"position":{"x":15194.967561329117,"y":18822.917975850924},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"bf788df7-d7bd-44f5-a1e2-f991b559eb67","savedPayload":{"position":{"x":15130.974543600076,"y":19171.566941484063},"targetPosition":{"x":15072.997768261408,"y":18877.22242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58","savedPayload":{"position":{"x":15072.997768261408,"y":18877.22242646581},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"e4644710-8f0c-462d-b981-a1dce5b8c73a","savedPayload":{"position":{"x":14864.068934676037,"y":19163.57876051796},"targetPosition":{"x":14939.54496379939,"y":18873.228335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a144fd80-7187-4237-8a1e-efc6927eb58f","savedPayload":{"position":{"x":14939.54496379939,"y":18873.228335982767},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"c31177a2-ed80-4eab-9b17-b4a6a17fd77a","savedPayload":{"position":{"x":14627.061232193264,"y":19040.575654564916},"targetPosition":{"x":14821.041112558003,"y":18811.726783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"725734c1-1636-4802-a3d7-40caa4b4f655","savedPayload":{"position":{"x":14821.041112558003,"y":18811.726783006245},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ddc7e432-cf87-475e-8af1-ddd2209fde78","savedPayload":{"position":{"x":12922.12874157189,"y":18026.027645942188},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"25a3b187-cb00-4569-881a-e8599a2ac9bf","savedPayload":{"position":{"x":15157.40991376369,"y":19105.46089514218},"targetPosition":{"x":14994.018203259182,"y":18853.859724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7807b9a3-05ea-421c-8584-d363dff6ca7a","savedPayload":{"position":{"x":14994.018203259182,"y":18853.859724758553},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"498ac6aa-2b55-4793-b2fe-0fd647ae7512","savedPayload":{"position":{"x":14768.252985509347,"y":18895.702834595064},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"43c595ce-8ba1-4a6a-b126-38898e46c880"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"f65fd57b-fd01-440e-a825-098fff6c4952","savedPayload":{"position":{"x":14579.025322371048,"y":18765.65026487943},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d"}}}],"id":"d481800e-4a37-4638-a095-e03282974b8d","savedPayload":{"position":{"x":12902.74809864453,"y":17841.63314577412},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"8463545a-e7e6-46d1-975c-729f23eaa7d2","savedPayload":{"position":{"x":14638.654978611017,"y":19108.731176915182},"targetPosition":{"x":14654.3557654839,"y":18809.142316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"0fbd4479-d451-4f8a-8452-27171db16d82","savedPayload":{"position":{"x":14654.3557654839,"y":18809.142316488807},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"63eacfe5-505a-4634-bb5e-c63214b48ebd","savedPayload":{"position":{"x":14447.113104713566,"y":18710.2926379701},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"eed08a75-d991-4dd6-98d1-6e0ee70dd04e","savedPayload":{"position":{"x":14370.467691930411,"y":18493.852669189557},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58"}}}],"id":"3bfca508-8cbb-4bad-8473-b0e8d785069e","savedPayload":{"position":{"x":12995.453196957013,"y":17681.06320537623},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"a280c06f-5e9c-44b4-906c-0bd88866c1e4","savedPayload":{"position":{"x":14217.05119675962,"y":18806.46039000926},"targetPosition":{"x":14405.84731407457,"y":18573.31660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"ff24e3b0-c186-4d2b-8722-e19f72075d41","savedPayload":{"position":{"x":14405.84731407457,"y":18573.31660157217},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"cffa95e0-222b-46da-b1db-5ca83d0dc237","savedPayload":{"position":{"x":14296.28686277904,"y":18371.531352115377},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"a144fd80-7187-4237-8a1e-efc6927eb58f"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"adc73235-49b3-4e74-a451-0a4ba69e0547","savedPayload":{"position":{"x":14361.499642952429,"y":18151.376695820127},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"725734c1-1636-4802-a3d7-40caa4b4f655"}}}],"id":"c6488672-2e9b-43a6-b6de-a398ea651320","savedPayload":{"position":{"x":13164.833839884375,"y":17605.650084408968},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"4ff7b240-bdd0-4f1d-8e31-5f9084686c69","savedPayload":{"position":{"x":13196.19237886467,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"4fae804c-e7d9-4f8f-9441-59e26185fff7","savedPayload":{"position":{"x":13715.807621135333,"y":17324.451157246007},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c5312c7b-f55e-43b7-943e-902588c25c9b","savedPayload":{"position":{"x":14005.585369022052,"y":17402.096870776764},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cdda2164-3e6b-4817-acbc-891388443917","savedPayload":{"position":{"x":13793.453334666088,"y":17614.228905132728},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"b9258e5a-1bef-4144-b489-3a65a5c867af","savedPayload":{"position":{"x":14125.615242270664,"y":17494.199031884116},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"9a9c7c68-f24e-4c5e-9e29-34b8260df057","savedPayload":{"position":{"x":14275.615242270664,"y":17754.00665301945},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2ce1a18f-aa45-4b1e-a01b-2125ebf93c8e","savedPayload":{"position":{"x":13975.615242270664,"y":17754.00665301945},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"ea88a867-d92e-4680-a40b-ec580bd80df2","savedPayload":{"position":{"x":14295.363116908775,"y":17904.00665301945},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"6430bee3-15e0-4598-a686-2ebc5f4ec6f5","savedPayload":{"position":{"x":14217.717403378017,"y":18193.78440090617},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"39efdc4e-0784-48c0-a39b-0dc54548cb77","savedPayload":{"position":{"x":14005.585369022054,"y":17981.652366550206},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"775abeea-a292-46a5-aebb-f8c0bfef7ca0","savedPayload":{"position":{"x":13715.807621135333,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"fdffbdff-a42f-47db-b068-4a711070bef3","savedPayload":{"position":{"x":13456.000000000002,"y":18054.00665301945},"targetPosition":{"x":13456.000000000002,"y":18354.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"5a1c468b-1e45-414b-8710-952a78fe831c","savedPayload":{"position":{"x":13456.000000000002,"y":18354.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Average VS Average Plotter","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = 1","project":"Superalgos","id":"80edad17-0f41-4dbb-864e-c2b257b06dde","savedPayload":{"position":{"x":13012.422735946908,"y":17744.918604065882},"targetPosition":{"x":13457.320310615743,"y":17677.345324925474},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c695315b-a12a-4972-8363-a3812215a54e","savedPayload":{"position":{"x":13457.320310615743,"y":17677.345324925474},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = 1","project":"Superalgos","id":"bf6adc6e-9aaf-434a-a41d-12a97f076653","savedPayload":{"position":{"x":13010.390506126048,"y":17488.75995637569},"targetPosition":{"x":13456.304195705314,"y":17549.266001080377},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c","savedPayload":{"position":{"x":13456.304195705314,"y":17549.266001080377},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.bullPriceDeviation","project":"Superalgos","id":"52a0dcca-d50d-4dfa-adb0-d6a2d2593187","savedPayload":{"position":{"x":13080.608826662963,"y":17242.404988482835},"targetPosition":{"x":13491.413355973771,"y":17426.08851713395},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf","savedPayload":{"position":{"x":13491.413355973771,"y":17426.08851713395},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.bullPriceDeviation","project":"Superalgos","id":"18676f64-51d5-4480-8ca7-398a8cf45098","savedPayload":{"position":{"x":13217.389026832188,"y":17025.81191475659},"targetPosition":{"x":13559.803456058384,"y":17317.791980270827},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f","savedPayload":{"position":{"x":13559.803456058384,"y":17317.791980270827},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.volumeDeviation","project":"Superalgos","id":"9cf7a19a-ff50-46ca-86c3-f8412d4e53ee","savedPayload":{"position":{"x":13409.64998827918,"y":16856.527817901653},"targetPosition":{"x":13655.93393678188,"y":17233.14993184336},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19","savedPayload":{"position":{"x":13655.93393678188,"y":17233.14993184336},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.volumeDeviation","project":"Superalgos","id":"c14b45db-6a55-4b02-83d3-f9c758bcdbde","savedPayload":{"position":{"x":13641.815871327472,"y":16748.267088673914},"targetPosition":{"x":13772.016878306025,"y":17179.01956722949},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82","savedPayload":{"position":{"x":13772.016878306025,"y":17179.01956722949},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.openInterestDeviation","project":"Superalgos","id":"afc254ff-402b-4632-952a-3a8504eb2f11","savedPayload":{"position":{"x":13895.07797687616,"y":16709.800367504067},"targetPosition":{"x":13898.64793108037,"y":17159.786206644567},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"803aaa7c-ad01-4bad-9943-f4fac99e4987","savedPayload":{"position":{"x":13898.64793108037,"y":17159.786206644567},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.openInterestDeviation","project":"Superalgos","id":"2d21a7f4-e6ea-47c2-85ec-4638fd68d0bd","savedPayload":{"position":{"x":14148.91851534143,"y":16744.243999370883},"targetPosition":{"x":14025.568200313004,"y":17177.008022577975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2","savedPayload":{"position":{"x":14025.568200313004,"y":17177.008022577975},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.smaPrice","project":"Superalgos","id":"d2a3c177-7426-4111-9e6e-80bd2ddd2ecc","savedPayload":{"position":{"x":14382.77283594463,"y":16848.80756606468},"targetPosition":{"x":14142.495360614605,"y":17229.289805924873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"de30fcce-febc-4c65-8908-852b2c91a3d9","savedPayload":{"position":{"x":14142.495360614605,"y":17229.289805924873},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.smaPrice","project":"Superalgos","id":"0bfdd80f-4420-4333-a60e-ac5afe17df21","savedPayload":{"position":{"x":14577.695452415694,"y":17015.01994927541},"targetPosition":{"x":14239.956668850136,"y":17312.39599753024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2","savedPayload":{"position":{"x":14239.956668850136,"y":17312.39599753024},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f20cacf7-c7ce-4a35-a06d-15951850e570","savedPayload":{"position":{"x":13902.21788528458,"y":17609.772045785066},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"62cd1b53-a0fd-4f09-a9c0-9bb7ac3ac642","savedPayload":{"position":{"x":13606.622714372208,"y":17333.07957471211},"targetPosition":{"x":13836.436047307901,"y":17525.91585761807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8eca09c2-69dc-4768-b3e4-08fa7f68b8e6","savedPayload":{"position":{"x":13836.436047307901,"y":17525.91585761807},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"af6872e7-8d5d-451e-802c-de5f614ea534","savedPayload":{"position":{"x":14040.102657419297,"y":17419.89373109651},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"9bfa8714-fe8d-4631-b9ca-8236b9f989b7","savedPayload":{"position":{"x":14259.085663149557,"y":17488.93880758834},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}}],"id":"ed0185c6-e131-4acf-983c-8ddfe5f1c523","savedPayload":{"position":{"x":14066.249380243595,"y":17718.752140524033},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice > record.previous.smaPrice","project":"Superalgos","id":"6f7dcb6c-ae19-46b2-a082-916dae93a16b","savedPayload":{"position":{"x":14003.00510583763,"y":16806.807443877766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"5860dc00-e1a5-4c65-bd4e-843091d935ce","savedPayload":{"position":{"x":13702.103077599852,"y":16642.91315569686},"targetPosition":{"x":13998.409579778392,"y":16689.843495208926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"675151a8-9c7d-4c48-860d-00e52056eec5","savedPayload":{"position":{"x":13998.409579778392,"y":16689.843495208926},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bf8ec324-5a02-4895-80ac-46fd519aa77c","savedPayload":{"position":{"x":13783.131983344476,"y":16423.274695891418},"targetPosition":{"x":14038.924032650704,"y":16580.024265306205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f7367289-76e5-48d5-a910-0c6636e8869c","savedPayload":{"position":{"x":14038.924032650704,"y":16580.024265306205},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"a74fa0b1-3291-4e48-a1e2-6fed290b521e","savedPayload":{"position":{"x":14118.38050626919,"y":16494.068736408506},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"33d6f2c5-3db4-42ce-8766-f408840b78e0","savedPayload":{"position":{"x":14224.682472800161,"y":16445.062858601686},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8ca3ff70-71b8-41a7-b184-2d85d95c29f4","savedPayload":{"position":{"x":14341.646421469002,"y":16440.46733254245},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"b711c638-8290-4d76-a1f4-96a9019c6b3d","savedPayload":{"position":{"x":14451.465651371718,"y":16480.981785414766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"a7e542dd-3221-4a1a-ab83-16a44d001416","savedPayload":{"position":{"x":14170.041816598648,"y":17727.832802064837},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice < record.previous.smaPrice","project":"Superalgos","id":"da6fa977-095e-439d-90a2-7e226c210bd1","savedPayload":{"position":{"x":14090.2888941966,"y":16657.139460121613},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"9e2a011a-4aa8-463c-a10c-dd18e0534a50","savedPayload":{"position":{"x":13863.588626615938,"y":16400.214652104183},"targetPosition":{"x":14125.974538757757,"y":16545.657538178082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d395d4a9-883b-49e9-90ae-a83f2fe2f59d","savedPayload":{"position":{"x":14125.974538757757,"y":16545.657538178082},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"941bac99-ea7f-4f0f-b149-3cf34f766cb0","savedPayload":{"position":{"x":14014.851668917005,"y":16221.535530140533},"targetPosition":{"x":14201.60605990829,"y":16456.317977196257},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"2ce85b80-0291-4b52-a297-72dd5e780d6e","savedPayload":{"position":{"x":14201.60605990829,"y":16456.317977196257},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"775e669a-6800-4190-9cad-dbae717911f5","savedPayload":{"position":{"x":14305.669244154476,"y":16402.721915470484},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"0a680163-5643-4a13-b55b-5fb80edde733","savedPayload":{"position":{"x":14422.321415029948,"y":16393.028867549005},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"cb32f3a6-681d-4df5-bdfc-14270081099b","savedPayload":{"position":{"x":14533.803336973477,"y":16428.71451211016},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"e50f0167-e004-4f8a-b593-1729a14e7c0d","savedPayload":{"position":{"x":14623.1428979553,"y":16504.346033260696},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"57807fe3-2d38-4767-8cee-b0d9091d358e","savedPayload":{"position":{"x":14264.469033973206,"y":17771.86493666486},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation > record.previous.volumeDeviation","project":"Superalgos","id":"5579428b-bd6e-44f1-b53a-9b9b9948b091","savedPayload":{"position":{"x":14231.426213757817,"y":16531.507148561304},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bbe1b239-e08b-440e-971a-49c3ee92a19a","savedPayload":{"position":{"x":14151.518676912645,"y":16186.158059796802},"targetPosition":{"x":14321.74863834028,"y":16433.183888876167},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"826e811a-3650-45c8-914d-b9cdb25c7624","savedPayload":{"position":{"x":14321.74863834028,"y":16433.183888876167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"4393fca4-e15d-4170-a127-5862e8c845a2","savedPayload":{"position":{"x":14445.787194516954,"y":16383.787124213184},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8c390826-ef92-470f-bd4f-4fb5aa2995a6","savedPayload":{"position":{"x":14578.97452500399,"y":16393.100489625405},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"aa9b0281-5501-4ecf-8747-03df65df1b82","savedPayload":{"position":{"x":14694.931245563015,"y":16459.27935887202},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"114e6dce-ec3c-4ab1-b7f4-5f72f36eeabb","savedPayload":{"position":{"x":14770.690705571464,"y":16569.216195268167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"d42bf0ab-d03e-4a30-a896-d27fdbe4fa98","savedPayload":{"position":{"x":14338.14171635459,"y":17845.537619046245},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation < record.previous.volumeDeviation","project":"Superalgos","id":"ba7ccc38-7438-4fd9-8d17-1f7d1c4bff39","savedPayload":{"position":{"x":14157.277178666109,"y":16579.923368208143},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"43749c18-0468-43de-9198-abb8d04541dc","savedPayload":{"position":{"x":14018.614376933985,"y":16253.69670625219},"targetPosition":{"x":14229.153747799182,"y":16467.409535337592},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"1c2a8a8c-9619-43e6-b564-f478e699a656","savedPayload":{"position":{"x":14229.153747799182,"y":16467.409535337592},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"564d9677-fff2-429f-8dd1-61233ab23d60","savedPayload":{"position":{"x":14342.73022142804,"y":16397.224149283244},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"7aacc15f-eba7-4455-a74a-23ba60467128","savedPayload":{"position":{"x":14475.511386026454,"y":16383.268286520444},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"9b74661e-c05a-4407-9e2d-f387f2b439e2","savedPayload":{"position":{"x":14601.198303491585,"y":16428.30607682678},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"478698e3-2c63-421d-b25c-bd6e641d76a2","savedPayload":{"position":{"x":14694.897138370581,"y":16523.417233479846},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"fb723dee-63a8-46c2-afc4-48210897864c","savedPayload":{"position":{"x":14382.173850954614,"y":17939.9648364208},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"openInterestDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 2,\n 7\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"30cdd628-da04-4589-b126-db7da41f9b45","savedPayload":{"position":{"x":14668.977724920003,"y":16163.768375838048},"targetPosition":{"x":14674.213446851189,"y":16463.722684384968},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"5ea53d11-e359-484f-920c-76c642c44018","savedPayload":{"position":{"x":14674.213446851189,"y":16463.722684384968},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"openInterestDeviation Begin","project":"Superalgos","id":"39e8c351-78ce-4df3-abd0-24512243c73a","savedPayload":{"position":{"x":14887.846679920072,"y":16547.875052830295},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation Begin","id":"803aaa7c-ad01-4bad-9943-f4fac99e4987"}}},{"type":"Polygon Vertex","name":"openInterestDeviation End","project":"Superalgos","id":"b4b2a034-19f0-4069-bb3b-dedf524bb993","savedPayload":{"position":{"x":14979.403477329291,"y":16758.441271000705},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation End","id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2"}}}],"id":"b38a785b-70da-4d5c-bf56-064fcc5d55b8","savedPayload":{"position":{"x":14391.254512495416,"y":18043.757272775856},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"bullPriceDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 3,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"345cc144-aed2-4aaf-9e5d-8a9e628704a2","savedPayload":{"position":{"x":14936.030764208717,"y":16280.656443637166},"targetPosition":{"x":14838.360317871571,"y":16564.312016316962},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f0e9511b-24df-4a07-90df-78bed13778e0","savedPayload":{"position":{"x":14838.360317871571,"y":16564.312016316962},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"bullPriceDeviation Begin","project":"Superalgos","id":"6c8f60ee-9ee0-4a0f-bf00-1519a8ba31ec","savedPayload":{"position":{"x":15010.328085424175,"y":16716.456244960038},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation Begin","id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf"}}},{"type":"Polygon Vertex","name":"bullPriceDeviation End","project":"Superalgos","id":"31202df8-551d-48cb-87ee-a782dc2fd278","savedPayload":{"position":{"x":15024.34544421422,"y":16945.63803533391},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation End","id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f"}}}],"id":"137e3254-785f-4469-84f6-b654b34fe6b5","savedPayload":{"position":{"x":14364.288439178888,"y":18144.39602847377},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"33e571bd-9a26-4e88-8427-5b863d0aed70","savedPayload":{"position":{"x":14092.396103067893,"y":18017.610549951558},"targetPosition":{"x":13880.26406871193,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"13acaaae-6a8e-4e48-a326-9d209079629f","savedPayload":{"position":{"x":13880.26406871193,"y":18229.74258430752},"targetPosition":{"x":13668.132034355966,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3548ecec-25e1-4bb8-86c5-9743052bd80b","savedPayload":{"position":{"x":13668.132034355966,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b4f0c498-27c5-4c28-acef-67ff7f317e38","savedPayload":{"position":{"x":13456.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}} \ No newline at end of file From 92c3d189a1609ca64012de4a1ec060fb42f13002 Mon Sep 17 00:00:00 2001 From: cozed-gh <76752164+cozed-gh@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:28:02 +0200 Subject: [PATCH 19/32] Name change to Omega-One --- Projects/Superalgos/Plugins/Data-Mines/Omega-One.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Projects/Superalgos/Plugins/Data-Mines/Omega-One.json diff --git a/Projects/Superalgos/Plugins/Data-Mines/Omega-One.json b/Projects/Superalgos/Plugins/Data-Mines/Omega-One.json new file mode 100644 index 000000000..c9f447b78 --- /dev/null +++ b/Projects/Superalgos/Plugins/Data-Mines/Omega-One.json @@ -0,0 +1 @@ +{"type":"Data Mine","name":"Omega One","config":"{\n \"codeName\": \"Omega-One\"\n}","project":"Superalgos","sensorBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Chaikin Oscillator","project":"Superalgos","id":"130f1639-b299-4ca8-96eb-25c8345e09e4","savedPayload":{"position":{"x":13957.729481237811,"y":17901.141979655422},"targetPosition":{"x":14015.96376638588,"y":18118.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"5b0389ae-3da9-4628-bc20-1041faef76be"}}}],"outputDatasetFolders":[],"id":"e54488da-6999-437b-8a2d-85709728bb02","savedPayload":{"position":{"x":14015.96376638588,"y":18118.475290570463},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"1ff01e67-048e-4d80-a944-b1b86f21f42b","savedPayload":{"position":{"x":14143.886491396086,"y":17681.058769490315},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"c4fcc40a-427d-4c69-90a9-76abdc87b857","savedPayload":{"position":{"x":14214.185526065303,"y":17677.374553197562},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"2cb0d0f1-a9dc-4791-9952-0878eeaa96bd","savedPayload":{"position":{"x":14282.182366522136,"y":17695.594251685838},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"6e898c07-cb2e-4589-bd33-9b3c6b585bae","savedPayload":{"position":{"x":14341.221008260825,"y":17733.93439392301},"targetPosition":{"x":14190.666621830082,"y":17901.141979655422},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"2ea98444-5707-42c3-a6d0-0c4d7cceec15","savedPayload":{"position":{"x":14190.666621830082,"y":17901.141979655422},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"3364b7b3-93c0-49e5-8ea2-c18fce0cec74","savedPayload":{"position":{"x":14392.396103067893,"y":18017.610549951558},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"4a247a06-dfc4-400b-a3b8-fa9d57847f6a","savedPayload":{"position":{"x":14291.531362448988,"y":18277.574316337435},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"9d6d825e-c8cf-4d42-828c-62a1ba12bd32","savedPayload":{"position":{"x":14291.531362448988,"y":18394.04288663357},"targetPosition":{"x":14074.198051533947,"y":18335.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e51bc1f1-1063-4d69-9699-3952ad33a056","savedPayload":{"position":{"x":14074.198051533947,"y":18335.808601485503},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Chaikin Oscillator","project":"Superalgos","id":"3d8886e0-c7a2-43aa-91c4-7698757a50e8","savedPayload":{"position":{"x":14656.000000000002,"y":17874.58378961345},"targetPosition":{"x":14431.000000000002,"y":18264.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108"}}}],"outputDatasetFolders":[],"id":"7ed09a77-8e5a-4f61-a182-ed93aa9e8037","savedPayload":{"position":{"x":14431.000000000002,"y":18264.29522131645},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Chaikin Oscillator Multi-Period-Daily","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"61339b0d-ee5d-4848-a59c-b3f6d5ecfc07","savedPayload":{"position":{"x":14820.711431703,"y":18039.29522131645},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"21243e1a-a52f-40f7-9087-483a49a574a8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"b0e714a3-f496-407a-b1e5-b722df1b8e96","savedPayload":{"position":{"x":14913.909483236945,"y":18110.808601485503},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{\n \"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"7ddfb356-e8b3-4e49-9642-670f81d29b29","savedPayload":{"position":{"x":14985.422863405996,"y":18204.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"3ed165f6-6c65-445f-b70a-70275435ffca","savedPayload":{"position":{"x":15030.37805353308,"y":18312.538082723313},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"d9dc3be3-7565-4801-9d18-2b25380dcf87","savedPayload":{"position":{"x":15045.711431703,"y":18429.00665301945},"targetPosition":{"x":14595.711431703,"y":18429.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"50b4b77b-7aae-4fb8-b147-4e77438e3278","savedPayload":{"position":{"x":14595.711431703,"y":18429.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"21243e1a-a52f-40f7-9087-483a49a574a8","savedPayload":{"position":{"x":14656.000000000002,"y":18654.00665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"124bcc91-61a1-40a1-a0b8-08179b8c16f6","savedPayload":{"position":{"x":14400.855715851501,"y":18766.50665301945},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"ffa4c8b2-81bc-4f09-a54b-7fc71543b8f5","savedPayload":{"position":{"x":14318.500000000002,"y":18848.86236887095},"targetPosition":{"x":14206.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"9c9a84d7-7bcf-4ffa-96db-a4a0b51d8e93","savedPayload":{"position":{"x":14206.000000000002,"y":18654.00665301945},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"singularVariableName\": \"chaikinOscillator\",\n \"pluralVariableName\": \"chaikinOscillators\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"5b0389ae-3da9-4628-bc20-1041faef76be","savedPayload":{"position":{"x":14264.438536534506,"y":18819.208347863343},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"5ad27a57-7fbf-43fd-9945-6b42a0660108","savedPayload":{"position":{"x":14235.433991612475,"y":19002.335837297276},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"3b204f99-f7d6-4d97-96f5-9e0f6cbc0558","savedPayload":{"position":{"x":14833.139338556775,"y":19494.60328091257},"targetPosition":{"x":14536.832836378235,"y":19447.672941400502},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cc3721e3-1409-4d80-8b1d-2d76ee03aefa","savedPayload":{"position":{"x":14536.832836378235,"y":19447.672941400502},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"a7081fb9-9143-463f-8e64-270dda8190dc","savedPayload":{"position":{"x":14664.790402911622,"y":19825.00667060036},"targetPosition":{"x":14452.658368555658,"y":19612.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"128aca84-d3ff-45ec-a8d2-b1fd4e942274","savedPayload":{"position":{"x":14452.658368555658,"y":19612.874636244396},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if ( isNaN(variable.chaikinOscillator ) )\n{ variable.chaikinOscillator = 0 }\nelse\n{ variable.chaikinOscillator }","project":"Superalgos","id":"eefbdfb1-b1b7-46c9-b283-f6de0dd556d1","savedPayload":{"position":{"x":14310.921843467799,"y":19845.202355156245},"targetPosition":{"x":14287.456673711764,"y":19697.049104066973},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7f4e57b6-1d97-4902-8c5b-04d0ddaac1e6","savedPayload":{"position":{"x":14287.456673711764,"y":19697.049104066973},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Zero Line","config":"{\n \"codeName\": \"zeroLine\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"0","project":"Superalgos","id":"45c55257-fc58-4b76-9310-6471ff58182a","savedPayload":{"position":{"x":14036.230609316899,"y":19801.695537773197},"targetPosition":{"x":14104.32918427783,"y":19668.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3a6a9b74-37a9-48c4-956c-a6d6a5ae0080","savedPayload":{"position":{"x":14104.32918427783,"y":19668.044559144942},"targetPosition":{"x":14240.526334199694,"y":19400.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"28f4f675-6764-4e30-b797-0ea44a6dfa53","savedPayload":{"position":{"x":14240.526334199694,"y":19400.742601888433},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Loop Code */\n\n/* Chaikin Oscillator\n\nKEY TAKEAWAYS\n- The Chaikin Indicator applies MACD to the accumulation-distribution line rather than closing price.\n- A cross above the accumulation-distribution line indicates that market players are accumulating shares, securities or contracts, which is typically bullish.\n\n1. Money Flow Multiplier = [(Close - Low) - (High - Close)] / (High - Low) \n2. Money Flow Volume = Money Flow Multiplier x Volume for the Period\n3. ADL = Previous ADL + Current Period's Money Flow Volume\n4. Chaikin Oscillator = ('fast'-period EMA of ADL) - ('slow'-period EMA of ADL) */\n\n\nlet fastPeriod = 5 // Change value to set 'fast' period (must be less than or equal to 'fast')\nlet slowPeriod = 17 // Change value to set 'slow' period (must be greater than or equal to 'slow')\n\nlet candle = record.current\nlet volume = getElement('volumes', candle)\n\n\n// Set varibles\nvariable.totalVolume = volume.buy + volume.sell\t\nvariable.moneyFlowMultiplier = ((candle.close - candle.min) - (candle.max - candle.close)) / (candle.max - candle.min) \nvariable.moneyFlowVolume = variable.moneyFlowMultiplier * variable.totalVolume \nvariable.currentADL = variable.totalVolume + variable.moneyFlowVolume\nvariable.savedADL.push(variable.currentADL) // Push the currentADL into an array to be able to use \"previous ADL\"\n\nif (variable.savedADL.length > 2) { // Make sure we only save the current and previous\n variable.savedADL.splice(0, 1)\n}\n\n// Calculating the 'accDistLine' using previous ADL value if it is defined, else current\nif (variable.savedADL[0] === 'undefined')\n{variable.accDistLine = variable.savedADL[1] + variable.moneyFlowVolume} // Calculating with Current ADL\nelse\n{variable.accDistLine = variable.savedADL[0] + variable.moneyFlowVolume} // Calculating with Previous ADL\n\n\n// Calculate fastEMA and slowEMA of ADL\nif(isNaN(variable.previousEmaFast))\n{variable.previousEmaFast = variable.accDistLine}\nelse\n{variable.previousEmaFast}\n\nvariable.fastEMA = calculateEMAs(fastPeriod, variable.accDistLine, variable.previousEmaFast)\nvariable.previousEmaFast = variable.fastEMA\n\nif(isNaN(variable.previousEmaSlow))\n{variable.previousEmaSlow = variable.accDistLine}\nelse\n{variable.previousEmaSlow}\nvariable.slowEMA = calculateEMAs(slowPeriod, variable.accDistLine, variable.previousEmaSlow)\nvariable.previousEmaSlow = variable.slowEMA\n\n\n// Create EMA function for 'fast' and 'slow' ADL\nfunction calculateEMAs(periods, adl, previousEMA) {\n let k = 2 / (periods + 1)\n return adl * k + previousEMA * (1-k)\n}\n\n// Calculate Chaikin Oscillator value\nvariable.chaikinOscillator = variable.fastEMA - variable.slowEMA\n\n// Happy trading! CJ.","project":"Superalgos","id":"43f087d9-6da9-4387-a3ee-7e7e4ca247b3","savedPayload":{"position":{"x":13947.33381066081,"y":19411.075663396023},"targetPosition":{"x":13936.880964334045,"y":19311.623473859196},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"2c6eff8c-0beb-4068-a9c6-26a06cbd242d","savedPayload":{"position":{"x":13936.880964334045,"y":19311.623473859196},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build arrays \n\nvariable.savedADL = []\n\n","project":"Superalgos","id":"67b6e8ff-b104-47c1-b8ec-a8847bce6b7a","savedPayload":{"position":{"x":13819.517534074947,"y":19390.831553964606},"targetPosition":{"x":13860.191198382527,"y":19299.477008200345},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"c6684774-9a86-4b1b-a1ef-5ddd2027ae00","savedPayload":{"position":{"x":13860.191198382527,"y":19299.477008200345},"targetPosition":{"x":13921.201694843896,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ba9d9a5f-61eb-49d8-a73d-15ca3e00ecd7","savedPayload":{"position":{"x":13921.201694843896,"y":19162.445189553953},"targetPosition":{"x":13968.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"31fee6c0-b932-4604-8a47-aa31fd679291","savedPayload":{"position":{"x":13968.132034355966,"y":18866.138687375413},"targetPosition":{"x":13756.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Chaikin Oscillator","id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae"}}}],"id":"f7bdd106-bdc2-4a99-8bce-173e94322727","savedPayload":{"position":{"x":13756.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Slow","project":"Superalgos","id":"4a233d99-e570-4936-a3f4-613c75213bc8","savedPayload":{"position":{"x":15567.729481237811,"y":17623.641979655422},"targetPosition":{"x":15625.963766385876,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c"}}}],"outputDatasetFolders":[],"id":"03c83aa5-5473-499d-8990-b99aa25cd543","savedPayload":{"position":{"x":15625.963766385876,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"af2be1a5-6589-49d4-8f89-8ae1cb3162f8","savedPayload":{"position":{"x":15686.182336682012,"y":17743.54743264471},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"ce465417-0658-430a-9888-2ffefee15357"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"24d1f7a4-66af-4169-a118-93618334f6ae","savedPayload":{"position":{"x":15771.549479256044,"y":17732.308635112942},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c541371a-27a9-436c-9342-081d67231318","savedPayload":{"position":{"x":15839.860194607763,"y":17784.725290570463},"targetPosition":{"x":15742.432336682012,"y":17840.975290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"6f23340b-8d1f-4652-876f-4a70c3e21aec","savedPayload":{"position":{"x":15742.432336682012,"y":17840.975290570463},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"ce465417-0658-430a-9888-2ffefee15357","savedPayload":{"position":{"x":16002.396103067893,"y":17740.110549951558},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"2597670e-3304-4839-ad6d-826290e3eabc","savedPayload":{"position":{"x":15901.531362448988,"y":18000.07431633744},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"96c24e28-6cd5-4d1f-9a35-35997b7e160a","savedPayload":{"position":{"x":15901.531362448988,"y":18116.542886633568},"targetPosition":{"x":15684.198051533947,"y":18058.308601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e0f2f6a8-0241-4aba-8751-a632e066d047","savedPayload":{"position":{"x":14118.132034355966,"y":18866.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Slow","project":"Superalgos","id":"1aedf3a0-5890-424e-a1f2-e54fc52659e1","savedPayload":{"position":{"x":16266.000000000002,"y":17597.08378961345},"targetPosition":{"x":16041.000000000002,"y":17986.79522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424"}}}],"outputDatasetFolders":[],"id":"d0cc5e79-a820-47d7-ad12-406b09b6f4dd","savedPayload":{"position":{"x":16041.000000000002,"y":17986.79522131645},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Slow Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"fd87cb30-87eb-4ba7-9763-da651e48813c","savedPayload":{"position":{"x":16450.79899745976,"y":17774.10489744401},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3d36499e-ce24-4f0d-9875-48f7b63d05c8","savedPayload":{"position":{"x":16555.42711435863,"y":17868.31247704702},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"77a7753f-af11-40ac-a65d-ca75123b04ea","savedPayload":{"position":{"x":16625.822623626736,"y":17990.24107572407},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"6efb002f-6126-42ca-93fe-21c67f833c60","savedPayload":{"position":{"x":16655.094722342554,"y":18127.955472710124},"targetPosition":{"x":16205.711431703001,"y":18151.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"b0367e88-7e82-42cd-944d-c4e9ca80d945","savedPayload":{"position":{"x":16205.711431703001,"y":18151.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"379710cb-b876-45b0-a4f1-7a76cb6cae08","savedPayload":{"position":{"x":16266.000000000002,"y":18376.50665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0b78bc25-8a2b-4a22-bcda-635f3b9b1187","savedPayload":{"position":{"x":16010.855715851498,"y":18489.00665301945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"4eec532d-30b6-4356-b69d-2460739799ce","savedPayload":{"position":{"x":15928.500000000002,"y":18571.362368870945},"targetPosition":{"x":15816.000000000002,"y":18376.50665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"160e01a5-da62-4b67-9042-68751949ee96","savedPayload":{"position":{"x":13986.330085889911,"y":19184.33673890936},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"singularVariableName\": \"slowARPS\",\n \"pluralVariableName\": \"slowARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"c32e024e-83fc-422d-9dec-7b7a4179f17c","savedPayload":{"position":{"x":13910.83713266845,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"00c464d1-0a2a-48ce-a9c0-c2819a9f3424","savedPayload":{"position":{"x":13760.83713266845,"y":19451.455642263958},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"9b3ec784-f875-4a31-9f2d-fdba3a4dd237","savedPayload":{"position":{"x":13968.132034355966,"y":20089.44374852799},"targetPosition":{"x":13725.426936043481,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"04be52be-03fa-4548-8ac1-11a688786301","savedPayload":{"position":{"x":13725.426936043481,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"be9d5502-b6ea-4109-931c-263e4ef39166","savedPayload":{"position":{"x":13835.392989106482,"y":20222.18279377747},"targetPosition":{"x":13659.057413418739,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d7f463c1-7208-4b96-8d46-893ee111e6f7","savedPayload":{"position":{"x":13659.057413418739,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"74a4a7e5-b4d5-46bd-9a3e-92c2705646cf","savedPayload":{"position":{"x":13621.779485199722,"y":20164.748029485323},"targetPosition":{"x":13575.426936043481,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"3fe424b8-a927-4a4b-b82a-9fe013546966","savedPayload":{"position":{"x":13575.426936043481,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"735b28dc-532e-471f-bcdd-84ea80114a0e","savedPayload":{"position":{"x":13482.721837730996,"y":20186.772597152503},"targetPosition":{"x":13482.721837730996,"y":20036.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"86568b58-7899-4b50-80cd-4223c5b2a528","savedPayload":{"position":{"x":13482.721837730996,"y":20036.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"bf2645de-583b-4051-9f17-38935cb7d421","savedPayload":{"position":{"x":13343.66419026227,"y":20164.748029485323},"targetPosition":{"x":13390.016739418512,"y":20022.08955204105},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e799bf00-cf17-4adb-92e9-d5c66bce7261","savedPayload":{"position":{"x":13390.016739418512,"y":20022.08955204105},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"7c4af3a5-a3d3-4569-9074-6e5605f53cc2","savedPayload":{"position":{"x":13218.218474199382,"y":20100.83024462123},"targetPosition":{"x":13306.386262043254,"y":19979.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"5d00b15c-7803-4044-8b44-166ea605e241","savedPayload":{"position":{"x":13306.386262043254,"y":19979.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"cde2b51c-7d16-4ee6-8b35-1dad3e18227f","savedPayload":{"position":{"x":13118.66419026227,"y":20001.275960684117},"targetPosition":{"x":13240.016739418512,"y":19913.108172840246},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"af19875c-861c-407e-9275-8fb2111277dc","savedPayload":{"position":{"x":13240.016739418512,"y":19913.108172840246},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"da247784-c47c-41ae-b764-519d47700a50","savedPayload":{"position":{"x":13054.746405398178,"y":19875.83024462123},"targetPosition":{"x":13197.404882842451,"y":19829.477695464986},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"56774359-2338-4b22-bf66-26835a7f1266","savedPayload":{"position":{"x":13197.404882842451,"y":19829.477695464986},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"79052dd4-e79c-4139-b034-a2b59a7cad5f","savedPayload":{"position":{"x":13032.721837730996,"y":19736.772597152503},"targetPosition":{"x":13182.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"30c88625-0df0-4647-9ebf-51a5ef868f58","savedPayload":{"position":{"x":13182.721837730996,"y":19736.772597152503},"targetPosition":{"x":13482.721837730996,"y":19736.772597152503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"8b9a90a7-170a-4f59-8132-bd890aab9a26","savedPayload":{"position":{"x":13482.721837730996,"y":19736.772597152503},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 17 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ. :-)","project":"Superalgos","id":"adea7d76-a792-4556-b017-093de9fe2b0f","savedPayload":{"position":{"x":13268.09683828102,"y":19536.760753427396},"targetPosition":{"x":13331.028877386005,"y":19459.0461572817},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a6150e04-c314-489d-824f-23afa0072a7e","savedPayload":{"position":{"x":13331.028877386005,"y":19459.0461572817},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"cc836ccb-c2dc-4ba5-9fcd-080a69c50b8a","savedPayload":{"position":{"x":13192.03182941918,"y":19432.066250449483},"targetPosition":{"x":13285.389872068901,"y":19396.22945549495},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"679b4d08-204b-4564-9324-19f7ed005c08","savedPayload":{"position":{"x":13285.389872068901,"y":19396.22945549495},"targetPosition":{"x":13425.426936043481,"y":19342.474263063155},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"ab30d1a8-1659-46d7-9620-b2783b58feef","savedPayload":{"position":{"x":13425.426936043481,"y":19342.474263063155},"targetPosition":{"x":13668.132034355966,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"e34788bb-3c57-4a14-abb5-451f35533e49","savedPayload":{"position":{"x":13668.132034355966,"y":19166.138687375413},"targetPosition":{"x":13668.132034355966,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Slow","id":"e12e90bd-bc37-42da-9f83-7b1506391bd9"}}}],"id":"81becef8-2376-47a7-8cdf-a559c45ed950","savedPayload":{"position":{"x":13668.132034355966,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market ARPS Fast","project":"Superalgos","id":"a4be096d-4fa4-44ba-983d-af202af96d7d","savedPayload":{"position":{"x":16144.729481237811,"y":17296.141979655422},"targetPosition":{"x":16202.96376638588,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"08336286-f6f1-4fa5-ba1e-912897063979"}}}],"outputDatasetFolders":[],"id":"0727df65-0f8c-4415-a85f-d9e322240273","savedPayload":{"position":{"x":16202.96376638588,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"5790535f-17f2-4ee0-bded-368ebd9489dc","savedPayload":{"position":{"x":16263.182336682012,"y":17416.04743264471},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"ee739a5f-2a9e-40d4-a557-8cb53521d7e3","savedPayload":{"position":{"x":16348.549479256048,"y":17404.808635112942},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"c926b53f-07cb-4d2c-8260-9dadc6bb2f1b","savedPayload":{"position":{"x":16416.86019460776,"y":17457.225290570463},"targetPosition":{"x":16319.432336682012,"y":17513.475290570463},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"73f3249b-2f51-4399-950d-186d6d68c78e","savedPayload":{"position":{"x":16319.432336682012,"y":17513.475290570463},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"1bfb1c32-5495-452d-81c3-5b575bfc09c1","savedPayload":{"position":{"x":16579.39610306789,"y":17412.610549951558},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"9261d5a5-4da2-4119-a78a-7d231491c2ee","savedPayload":{"position":{"x":16478.531362448986,"y":17672.57431633744},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"68b54ef4-857f-4a75-88ea-319ba92f5fd9","savedPayload":{"position":{"x":16478.531362448986,"y":17789.042886633568},"targetPosition":{"x":16261.198051533947,"y":17730.808601485503},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b138ab56-8d61-44f0-b0e9-27f171bbbfbe","savedPayload":{"position":{"x":13774.198051533947,"y":19272.204704553395},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily ARPS Fast","project":"Superalgos","id":"f679b2a9-f5ce-46fb-852e-be58c502a0da","savedPayload":{"position":{"x":16843,"y":17269.58378961345},"targetPosition":{"x":16618,"y":17659.29522131645},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9"}}}],"outputDatasetFolders":[],"id":"d4701ed1-5658-45b5-8835-14f1414491f3","savedPayload":{"position":{"x":16618,"y":17659.29522131645},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"ARPS Fast Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"258d211e-d162-4064-ab04-a6f36ae306e6","savedPayload":{"position":{"x":17027.79899745976,"y":17446.60489744401},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"82262685-1d6f-4c35-8584-3f13ad1b0921","savedPayload":{"position":{"x":17132.427114358637,"y":17540.81247704702},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"c7c3c7a8-4fb5-45f2-bb11-51d6cfdfda3e","savedPayload":{"position":{"x":17202.822623626736,"y":17662.74107572407},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"0f0a43f4-60d2-42fa-93fa-be2e21f8c302","savedPayload":{"position":{"x":17232.094722342554,"y":17800.455472710124},"targetPosition":{"x":16782.711431703,"y":17824.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}}],"dataMineDataDependencies":[],"id":"d29fbaa9-5eb9-4cb0-94e3-3ea6d18f20c2","savedPayload":{"position":{"x":16782.711431703,"y":17824.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"2c12b3a2-5072-4152-9ce5-382ce627a4cf","savedPayload":{"position":{"x":16843,"y":18049.00665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"0394d6ce-4648-4295-aa21-431adf475fe3","savedPayload":{"position":{"x":16587.855715851503,"y":18161.50665301945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"c90561ab-2b37-4df4-8f06-10e06ed4edee","savedPayload":{"position":{"x":16505.5,"y":18243.862368870945},"targetPosition":{"x":16393,"y":18049.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"8634ce99-462c-4cf4-b55a-e939bd458a6b","savedPayload":{"position":{"x":13456.000000000002,"y":19404.00665301945},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"ARPS Fast","config":"{\n \"codeName\": \"fastARPS\",\n \"singularVariableName\": \"fastARPS\",\n \"pluralVariableName\": \"fastARPSs\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"08336286-f6f1-4fa5-ba1e-912897063979","savedPayload":{"position":{"x":13290.798305156108,"y":19462.445189553953},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"0c30b8d6-f6a4-4f55-b496-d2438a9953f9","savedPayload":{"position":{"x":13107.670815722175,"y":19433.440644631923},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"aa7ec15b-6515-41b2-bcf8-caf282254a2f","savedPayload":{"position":{"x":17020.13933855677,"y":18701.881922864293},"targetPosition":{"x":16723.832836378235,"y":18748.81226237636},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0bdacd74-1544-46ef-80b8-c36764f748f1","savedPayload":{"position":{"x":16723.832836378235,"y":18748.81226237636},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"6ba23d0d-4820-44d9-882e-12b53e3340c5","savedPayload":{"position":{"x":17020.13933855677,"y":18889.60328091257},"targetPosition":{"x":16723.832836378235,"y":18842.672941400506},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"0fd74c82-d165-42ba-a60e-2557ef8f7469","savedPayload":{"position":{"x":16723.832836378235,"y":18842.672941400506},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate ARPS","config":"{\n \"codeName\": \"ARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.ARPS))\n{variable.ARPS = 0}\nelse {variable.ARPS}","project":"Superalgos","id":"3548eb27-ca3d-4b56-851d-815322a07af3","savedPayload":{"position":{"x":16828.479270084455,"y":19000.038326771228},"targetPosition":{"x":16694.8282914562,"y":18931.939751810296},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"70fe36c1-0c68-49e7-a2fa-8f60232ff4ef","savedPayload":{"position":{"x":16694.8282914562,"y":18931.939751810296},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bull","config":"{\n \"codeName\": \"apsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBull))\n{variable.apsBull = 0}\nelse {variable.apsBull}","project":"Superalgos","id":"1473d657-276b-406b-90e6-a66131604ff6","savedPayload":{"position":{"x":16745.724385733636,"y":19113.940653422378},"targetPosition":{"x":16639.658368555654,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"571474ac-c4ed-4ee7-af2c-e4a56098cfad","savedPayload":{"position":{"x":16639.658368555654,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate Aps Bear","config":"{\n \"codeName\": \"apsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.apsBear))\n{variable.apsBear = 0}\nelse {variable.apsBear}","project":"Superalgos","id":"0b9787b0-9547-4688-be4a-48a727f42e04","savedPayload":{"position":{"x":16631.822059082486,"y":19196.695537773197},"targetPosition":{"x":16563.723484121554,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e255bc82-518f-41e0-b9c5-dc573217cfb9","savedPayload":{"position":{"x":16563.723484121554,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Rate SMA","config":"{\n \"codeName\": \"SMA\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(variable.SMA))\n{variable.SMA = 0}\nelse {variable.SMA}","project":"Superalgos","id":"8e31b59b-6550-469d-a818-edb4b9eda503","savedPayload":{"position":{"x":16497.921843467797,"y":19240.20235515624},"targetPosition":{"x":16474.456673711764,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"4c52fc87-fac3-4a74-928c-beff9640f538","savedPayload":{"position":{"x":16474.456673711764,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage ARPS","config":"{\n \"codeName\": \"percentageARPS\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageARPS))\n{variable.percentageARPS = 0}\nelse {variable.percentageARPS}","project":"Superalgos","id":"47dd70e8-0226-4bda-835d-8b426fc2e23d","savedPayload":{"position":{"x":16357.13082493159,"y":19240.20235515624},"targetPosition":{"x":16380.595994687626,"y":19092.04910406697},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ce61113d-7b92-454d-9d22-557fb0532385","savedPayload":{"position":{"x":16380.595994687626,"y":19092.04910406697},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bull","config":"{\n \"codeName\": \"percentageApsBull\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBull))\n{variable.percentageApsBull = 0}\nelse {variable.percentageApsBull}","project":"Superalgos","id":"c456e845-561a-4761-b7d8-0424bdd76729","savedPayload":{"position":{"x":16223.230609316897,"y":19196.695537773197},"targetPosition":{"x":16291.329184277829,"y":19063.044559144942},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"b2f7070c-8430-4a3b-9477-b71fa1215cdb","savedPayload":{"position":{"x":16291.329184277829,"y":19063.044559144942},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"Percentage Aps Bear","config":"{\n \"codeName\": \"percentageApsBear\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isNaN(variable.percentageApsBear))\n{variable.percentageApsBear = 0}\nelse {variable.percentageApsBear}","project":"Superalgos","id":"231fd372-de75-42b8-827b-7a315ac96a7f","savedPayload":{"position":{"x":16109.328282665747,"y":19113.940653422378},"targetPosition":{"x":16215.394299843729,"y":19007.874636244396},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"ba0880ca-226d-4e4c-a2d6-620d6dc5cfe0","savedPayload":{"position":{"x":16215.394299843729,"y":19007.874636244396},"targetPosition":{"x":16427.52633419969,"y":18795.742601888433},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"867c1562-64d7-47d1-ab5b-6de88bc115dd","savedPayload":{"position":{"x":12709.264051131018,"y":19438.53298721914},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* USER DEFINED VALUES SECTION */\n\nlet nCandles = 3 // Change number periods\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \n\n// Build arrays\n\nvariable.lastNCandlesARPS.push(candle.max - candle.min)\nvariable.lastNCandlesSMA.push(candle.close)\nvariable.lastNCandlesApsBull.push(candle.max - candle.open)\nvariable.lastNCandlesApsBear.push (candle.open - candle.min)\n\n// console.log(variable.lastNCandlesARPS)\n\n// Keep arrays the correct size of nCandles\n\nif (variable.lastNCandlesARPS.length > nCandles) {\n variable.lastNCandlesARPS.splice(0, 1)\n}\n\nif (variable.lastNCandlesSMA.length > nCandles) {\n variable.lastNCandlesSMA.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBull.length > nCandles) {\n variable.lastNCandlesApsBull.splice(0, 1)\n}\n\nif (variable.lastNCandlesApsBear.length > nCandles) {\n variable.lastNCandlesApsBear.splice(0, 1)\n}\n\n\n// Call the functions\nvariable.smaARPS = calculateSMA(variable.lastNCandlesARPS, nCandles)\nvariable.smaSMA = calculateSMA(variable.lastNCandlesSMA, nCandles)\nvariable.smaApsBull = calculateSMA(variable.lastNCandlesApsBull, nCandles)\nvariable.smaApsBear = calculateSMA(variable.lastNCandlesApsBear, nCandles)\n\n// Build SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calc\n if (src.length < periods) { return 0 }\n \n let sum = 0 // Initialize sum variable\n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// Calc final ARPS ApsBull ApsBear SMA as Rate\n\nvariable.ARPS = variable.smaARPS\n\n\nif (variable.smaApsBull > variable.smaApsBear) \n{\n\tvariable.apsBull = variable.smaSMA + ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\nelse \n{\n\tvariable.apsBull = variable.smaSMA - ((variable.smaApsBull / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\n\nif (variable.smaApsBear > variable.smaApsBull) \n{\n\tvariable.apsBear = variable.smaSMA + ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBear - variable.smaApsBull) * 2)\n}\nelse \n{\n\tvariable.apsBear = variable.smaSMA - ((variable.smaApsBear / variable.smaARPS) * (variable.smaApsBull - variable.smaApsBear) * 2)\n}\n\nvariable.SMA = variable.smaSMA\n\n\n// Calc final ARPS ApsBull ApsBear as %\n\nvariable.percentageARPS = (variable.smaARPS/candle.close) *100\nvariable.percentageApsBull = (variable.smaApsBull/variable.smaARPS) *100\nvariable.percentageApsBear = (variable.smaApsBear/variable.smaARPS) *100\n\n\n// Happy trading! CJ! :-)","project":"Superalgos","id":"35a38ab1-ff66-4072-b82f-6cc2f56ff6f4","savedPayload":{"position":{"x":12698.93098962343,"y":19145.34046368026},"targetPosition":{"x":12798.383179160257,"y":19134.88761735349},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"77b480da-70d7-43ab-bd51-98044b9350be","savedPayload":{"position":{"x":12798.383179160257,"y":19134.88761735349},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 4 arrays \n\nvariable.lastNCandlesARPS = []\nvariable.lastNCandlesSMA = []\nvariable.lastNCandlesApsBull = [] \nvariable.lastNCandlesApsBear = [] \n","project":"Superalgos","id":"8b82130d-b51f-410c-82b3-34abb02bc3a4","savedPayload":{"position":{"x":12719.175099054848,"y":19017.524187094394},"targetPosition":{"x":12810.529644819107,"y":19058.197851401972},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"e1fcfd73-c477-4574-986f-85583fa489af","savedPayload":{"position":{"x":12810.529644819107,"y":19058.197851401972},"targetPosition":{"x":12947.561463465498,"y":19119.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"19eacb84-6904-4b79-aa5c-7f6c69c89b04","savedPayload":{"position":{"x":12947.561463465498,"y":19119.208347863343},"targetPosition":{"x":13243.867965644038,"y":19166.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b099e79b-ee47-4937-bf88-43f1a4f55a8c","savedPayload":{"position":{"x":13243.867965644038,"y":19166.138687375413},"targetPosition":{"x":13456.000000000002,"y":18954.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"ARPS Fast","id":"fdffbdff-a42f-47db-b068-4a711070bef3"}}}],"id":"b1eaf829-987d-4ddc-92c7-10edb3e0d194","savedPayload":{"position":{"x":13456.000000000002,"y":18954.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Indicator Bot","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Market\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Average VS Average","project":"Superalgos","id":"2edf9e6c-e713-45fc-9764-73f1465f1352","savedPayload":{"position":{"x":13298.615075075051,"y":18964.99615794743},"targetPosition":{"x":13123.757233747232,"y":18823.399069961215},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15"}}}],"outputDatasetFolders":[],"id":"322cf5e8-7f9d-4bdd-abed-5f78672b93a9","savedPayload":{"position":{"x":13123.757233747232,"y":18823.399069961215},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Market","config":"{\n \"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"87830a28-1634-48f8-a226-506c89ade476","savedPayload":{"position":{"x":13138.198836524625,"y":18920.974720510905},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Market","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"3ab9def4-53a1-458f-83d7-b3be09887d4e","savedPayload":{"position":{"x":13100.330725060212,"y":18979.28649860078},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Market","project":"Superalgos","id":"78ca9971-aa46-458f-b8d9-354426317bd4","savedPayload":{"position":{"x":13035.419976144436,"y":19004.20340059676},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Market","project":"Superalgos","id":"f51ac085-64ae-45c2-9467-e98eb801379d","savedPayload":{"position":{"x":12968.260289627915,"y":18986.208016830733},"targetPosition":{"x":13029.532181067105,"y":18891.857577936873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"9bf0483c-4825-4a46-9cf4-1b5262579fc1"}}}],"dataMineDataDependencies":[],"id":"85b582f1-7cc2-4535-ac54-7df234e3db4f","savedPayload":{"position":{"x":13029.532181067105,"y":18891.857577936873},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"a8737ab1-e419-4e69-b49a-86dd29187dd8","savedPayload":{"position":{"x":12878.503883151308,"y":19126.26173524281},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"885a6862-324a-4528-b842-8c40f0aafc97","savedPayload":{"position":{"x":12807.3023044332,"y":18856.659823302816},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"bf186655-c6bd-487d-ab02-65b7535b80b1","savedPayload":{"position":{"x":12738.843796457542,"y":18762.434770622694},"targetPosition":{"x":12948.899392419413,"y":18681.801981975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"f8c12a67-d98f-4a20-9f95-5e590321403f","savedPayload":{"position":{"x":13243.867965644038,"y":19316.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Period-Daily\"\n }\n}","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Daily Average VS Average","project":"Superalgos","id":"3d362705-7d3b-4205-af78-6aeeccd326b9","savedPayload":{"position":{"x":12749.31287115968,"y":19396.915298070246},"targetPosition":{"x":12702.275062689236,"y":18949.380445154526},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c"}}}],"outputDatasetFolders":[],"id":"41ea773f-0b13-4691-8393-f562352f89ee","savedPayload":{"position":{"x":12702.275062689236,"y":18949.380445154526},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"Average VS Average Multi-Period-Daily","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"627ead20-a71e-47c1-8d5d-42506ab2433d","savedPayload":{"position":{"x":12519.243573305126,"y":19360.475901093694},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec"}}},{"type":"Status Dependency","name":"Candles Volumes Multi-Period-Daily","config":"{\n \"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"de6cab83-afd5-4f5a-ad2e-1cf0fc07b7e8","savedPayload":{"position":{"x":12401.810255566577,"y":19357.400801445783},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"2a021da8-9feb-475e-90ab-1586968c17c7"}}},{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","config":"{ \n\"mainUtility\": \"Market Starting Point\"\n}","project":"Superalgos","id":"f0dea610-c1c0-4f2f-9d79-8e2cfc90b582","savedPayload":{"position":{"x":12289.174275450572,"y":19324.036504117143},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"181c7c34-7243-497a-9ddb-1b0067c6d66e"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Period-Daily","project":"Superalgos","id":"f54e9145-daed-48a1-a2bb-ce82ceec4b78","savedPayload":{"position":{"x":12189.011588862255,"y":19262.656730833613},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"678a567c-f08d-49b9-813b-4e54fd6afadb"}}},{"type":"Data Dependency","name":"Volumes Multi-Period-Daily","project":"Superalgos","id":"947c751a-393b-4499-88d0-54d112a2d923","savedPayload":{"position":{"x":12108.148117365956,"y":19177.444411709588},"targetPosition":{"x":12472.205764834682,"y":18912.941048177974},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"2e683057-f911-4105-bc77-16f2706d1915"}}}],"dataMineDataDependencies":[],"id":"03d0b6f4-795f-43f9-aed7-398ff9be2c31","savedPayload":{"position":{"x":12472.205764834682,"y":18912.941048177974},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"b37ab847-04bd-4c0d-9599-3d308e6be0ec","savedPayload":{"position":{"x":12291.179606750065,"y":18766.34895577042},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"b7661232-5ecd-42e5-b4e2-0387253c51cc","savedPayload":{"position":{"x":12431.46982776093,"y":18525.364496474027},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"f29d08f9-e7c8-490c-8fca-14851a0d3dc3"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"25b50fcf-ad3c-436c-90b4-9b83dfafd4fb","savedPayload":{"position":{"x":12449.689526249205,"y":18410.32984754675},"targetPosition":{"x":12655.237254218791,"y":18501.845592238806},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"90fe53a1-9c47-4b05-af43-8876c468d379","savedPayload":{"position":{"x":12925.669914110093,"y":19184.33673890936},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"products":[{"type":"Product Definition","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"singularVariableName\": \"averageVsAverage\",\n \"pluralVariableName\": \"averageVsAverages\"\n}","project":"Superalgos","datasets":[{"type":"Dataset Definition","name":"Multi-Period-Market","config":"{\n \"codeName\": \"Multi-Period-Market\",\n \"type\": \"Market Files\",\n \"validTimeFrames\": [\n \"24-hs\",\n \"12-hs\",\n \"08-hs\",\n \"06-hs\",\n \"04-hs\",\n \"03-hs\",\n \"02-hs\",\n \"01-hs\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period\",\n \"fileName\": \"Data.json\"\n}","project":"Superalgos","id":"400f9db6-00b8-48a4-b1ca-2fce23447a15","savedPayload":{"position":{"x":12767.532389956295,"y":19108.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},{"type":"Dataset Definition","name":"Multi-Period-Daily","config":"{\n \"codeName\": \"Multi-Period-Daily\",\n \"type\": \"Daily Files\",\n \"validTimeFrames\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset/@Period/@Year/@Month/@Day\",\n \"fileName\": \"Data.json\",\n \"dataRange\": {\n \"filePath\": \"Project/@Project/@MineType/@Mine/@Bot/@Exchange/@BaseAsset-@QuotedAsset/Output/@Product/@Dataset\",\n \"fileName\": \"Data.Range.json\"\n }\n}","project":"Superalgos","id":"ff8973cc-ff0d-432b-bb02-2ce87da7f59c","savedPayload":{"position":{"x":12658.551010755493,"y":18958.843785687895},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}}],"record":{"type":"Record Definition","name":"New Record Definition","project":"Superalgos","properties":[{"type":"Record Property","name":"Begin","config":"{\n \"codeName\": \"begin\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.begin))\n{record.current.begin = 0}\nelse {record.current.begin}","project":"Superalgos","id":"abf7c3f9-418d-44be-9d5f-68117e6e26cf","savedPayload":{"position":{"x":11465.997291705151,"y":19436.727492435068},"targetPosition":{"x":11890.26136041708,"y":19012.46342372314},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"fc0364a2-a5b0-4f77-81cb-448f3a532efb","savedPayload":{"position":{"x":11958.596466474826,"y":19114.405409046878},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"End","config":"{\n \"codeName\": \"end\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Formula","code":"if (isNaN(record.current.end))\n{record.current.end = 0}\nelse {record.current.end}","project":"Superalgos","id":"615b00d5-f0e5-48e4-883f-8985b00b7470","savedPayload":{"position":{"x":11245.31760010297,"y":19132.987954698667},"targetPosition":{"x":11779.92151461599,"y":18860.59365485494},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"20fcfc66-d336-4c0d-872f-50a5d8cd50b6","savedPayload":{"position":{"x":11811.493133483104,"y":18891.553385199248},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"bullPriceDeviation","config":"{\n \"codeName\": \"bullPriceDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.bullPriceDeviation)) {\nvariable.bullPriceDeviation\n}\nelse {\nvariable.bullPriceDeviation = 1\n}","project":"Superalgos","id":"fa9aa35e-98af-416d-b3b9-395327e5cd9d","savedPayload":{"position":{"x":11925.045623569087,"y":18640.3908017439},"targetPosition":{"x":12074.441767668373,"y":18653.836698079413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7bd05b9a-a315-4e3d-93b0-3943a7f3ba50","savedPayload":{"position":{"x":12074.441767668373,"y":18653.836698079413},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"smaPrice","config":"{\n \"codeName\": \"smaPrice\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.smaPrice)) {\nvariable.smaPrice\n}\nelse {\nvariable.smaPrice = 1\n}","project":"Superalgos","id":"63142088-1b62-4a15-985f-c53cd6adb314","savedPayload":{"position":{"x":11986.932098746105,"y":18449.923815917784},"targetPosition":{"x":12115.699417786385,"y":18526.85870752867},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"67b38c00-0e3d-47bc-942c-0fdda9625e9a","savedPayload":{"position":{"x":12115.699417786385,"y":18526.85870752867},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"volumeDeviation","config":"{\n \"codeName\": \"volumeDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.volumeDeviation)) {\nvariable.volumeDeviation\n}\nelse {\nvariable.volumeDeviation = 1\n}","project":"Superalgos","id":"6ec8c68a-20f5-4d3d-8ef5-1c0e87f0c5a3","savedPayload":{"position":{"x":12125.3304142135,"y":18305.170526575857},"targetPosition":{"x":12207.964961431315,"y":18430.35651463405},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"aa0f2fc4-d1de-49d8-87cb-d2d68b4bbb09","savedPayload":{"position":{"x":12207.964961431315,"y":18430.35651463405},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Record Property","name":"openInterestDeviation","config":"{\n \"codeName\": \"openInterestDeviation\",\n \"isString\": false,\n \"isCalculated\": false\n}","project":"Superalgos","recordFormula":{"type":"Record Formula","name":"New Record Formula","code":"if (isFinite(variable.openInterestDeviation)) {\nvariable.openInterestDeviation\n}\nelse {\nvariable.openInterestDeviation = 1\n}","project":"Superalgos","id":"3fde42f1-88e4-4a07-9f0d-ad1ceef8ae89","savedPayload":{"position":{"x":12312.829086249,"y":18234.80109795487},"targetPosition":{"x":12332.964076121649,"y":18383.44356222006},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"264be2f7-a27c-414b-8aee-7473c120b89f","savedPayload":{"position":{"x":12332.964076121649,"y":18383.44356222006},"targetPosition":{"x":12373.234055866946,"y":18680.728490750444},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"536bed44-cdea-4518-974c-4fbd6787c969","savedPayload":{"position":{"x":12373.234055866946,"y":18680.728490750444},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":5,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"dataBuilding":{"type":"Data Building Procedure","name":"New Data Building Procedure","project":"Superalgos","loop":{"type":"Procedure Loop","name":"New Procedure Loop","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"EDIT TOP LINES HERE TO CHANGE PERIODS","code":"// The Average VS Average Oscillator\n\n/* The Average VS Average Oscillator can be used to recognize changes between a fast average ('fastPeriod') and a slow average ('slowPeriod'). It measures 'Price Action', 'Volume', and a so called 'Open Interest'.\n'Bull Price Action' and 'Bear Price Action' is defined by the amount between the candle close and max and min.\n'Bull Volume' and 'Bear Volume' is divided using the price action.\n'Open Interest' is based upon the statement where:\nBull Candle and Volume Increase = Bull Interest\nBull Candle and Volume Decrease = Bear Interest\nBear Candle and Volume Increase = Bear Interest\nBear Candle and Volume Decrease = Bull Interest */\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n/* USER DEFINED VALUES SECTION */\n\nlet fastPeriod = 5 // Change this number to the period of your choice (must be less than 'slowPeriod')\nlet slowPeriod = 21 // Change this number to the period of your choice (must be greater than 'fastPeriod')\nlet periodMultiplier = 3 // The 'slowPeriod' is muliplied by the 'periodMultiplier to create the \"long term\" trend\nlet fastBoost = 1.00 // '1.00' equals 'no extra boost' to your 'fastPeriod' where as '1.23' would boost the value by 23%\nlet gravity = 0 // '0' equals 'no gravity' (pullback towards midline ('slowPeriod'))\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring variables used\n\nlet candle = {\n open: record.current.open,\n close: record.current.close,\n min: record.current.min,\n max: record.current.max,\n begin: record.current.begin,\n end: record.current.end\n} \nlet volCandle = record.current\nlet volume = getElement('volumes', volCandle)\nlet totalVolume = volume.buy + volume.sell\nlet totalRange = candle.max - candle.min\nlet multipliedFast = fastPeriod * periodMultiplier\nlet multipliedSlow = slowPeriod * periodMultiplier\n\nif ( candle.close > candle.open ) { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\nelse { \n variable.bullPriceRange = ( candle.close - candle.min ),\n variable.bearPriceRange = ( candle.max - candle.close )\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Volume Difference'\n\nvariable.previousCurrentVolume.push(totalVolume)\nif (variable.previousCurrentVolume.length > 2) {\n variable.previousCurrentVolume.splice(0, 1)\n}\n\nif (variable.previousCurrentVolume[1] === 'undefined') {\n variable.positiveVolumeDifference = 0.01\n}\nelse {\n if (variable.previousCurrentVolume[variable.previousCurrentVolume.max] > variable.previousCurrentVolume[0]) {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[1] - variable.previousCurrentVolume[0]) \n }\n else {\n variable.positiveTotalVolumeDifference = (variable.previousCurrentVolume[0] - variable.previousCurrentVolume[1])\n }\n}\n\nvariable.bullVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bullPriceRange / totalRange)\nvariable.bearVolumeDifference = variable.positiveTotalVolumeDifference * (variable.bearPriceRange / totalRange)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring 'Open Interest'\n// Converting values to percentages due to the differences of range and volume (range might be in decimals while volume often is in thousands)\n\nif ( candle.close > candle.open && variable.previousCurrentVolume[1] > variable.previousCurrentVolume[0] ) { // Candle UP & Volume UP, Bullish Interest\n variable.openInterest = 1 + ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close < candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle DOWN & Volume DOWN, Bullish Interest\n variable.openInterest = 1 + ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse if ( candle.close > candle.open && variable.previousCurrentVolume[1] < variable.previousCurrentVolume[0] ) { // Candle UP & Volume DOWN, Bearish Interest\n variable.openInterest = 1 - ((variable.bullPriceRange / totalRange) * (variable.bullVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\nelse { // Candle DOWN & Volume UP, Bearish Interest\n variable.openInterest = 1 - ((variable.bearPriceRange / totalRange) * (variable.bearVolumeDifference / variable.positiveTotalVolumeDifference))\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Saving to arrays\n\nvariable.savedCandleClose.push(candle.close)\nif (variable.savedCandleClose.length > multipliedSlow) {\n variable.savedCandleClose.splice(0, 1)\n}\n\nvariable.savedTotalRange.push(totalRange)\nif (variable.savedTotalRange.length > multipliedSlow) {\n variable.savedTotalRange.splice(0, 1)\n}\n\nvariable.savedBullPriceRange.push(variable.bullPriceRange)\nif (variable.savedBullPriceRange.length > multipliedSlow) {\n variable.savedBullPriceRange.splice(0, 1)\n}\n\nvariable.savedTotalVolume.push(totalVolume)\nif (variable.savedTotalVolume.length > multipliedSlow) {\n variable.savedTotalVolume.splice(0, 1)\n}\n\nvariable.savedOpenInterest.push(variable.openInterest)\nif (variable.savedOpenInterest.length > multipliedSlow) {\n variable.savedOpenInterest.splice(0, 1)\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Calling SMA functions\n\nvariable.smaMultipliedFastCandleClose = calculateSMA(variable.savedCandleClose, multipliedFast)\nvariable.smaSlowCandleClose = calculateSMA(variable.savedCandleClose, slowPeriod)\nvariable.smaLongTermCandleClose = calculateSMA(variable.savedCandleClose, multipliedSlow)\n\nvariable.smaFastTotalRange = calculateSMA(variable.savedTotalRange, fastPeriod)\nvariable.smaSlowTotalRange = calculateSMA(variable.savedTotalRange, slowPeriod)\nvariable.smaLongTermRange = calculateSMA(variable.savedTotalRange, multipliedSlow)\n\nvariable.smaFastBullPriceRange = calculateSMA(variable.savedBullPriceRange, fastPeriod)\nvariable.smaSlowBullPriceRange = calculateSMA(variable.savedBullPriceRange, slowPeriod)\n\nvariable.smaFastTotalVolume = calculateSMA(variable.savedTotalVolume, fastPeriod)\nvariable.smaLongTermTotalVolume = calculateSMA(variable.savedTotalVolume, multipliedSlow)\n\nvariable.smaFastOpenInterest = calculateSMA(variable.savedOpenInterest, fastPeriod)\nvariable.smaSlowOpenInterest = calculateSMA(variable.savedOpenInterest, slowPeriod)\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Creating the SMA function\n\nfunction calculateSMA(src, periods) { \n // Check we have enough values to make the calculation\n if (src.length < periods) { return 0 }\n \n // Initialize sum variable\n let sum = 0 \n for (let i = src.length - periods; i < src.length; i++) {\n sum = sum + src[i]\n }\n let sma = sum / periods\n return sma\n}\n\n// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n// Declaring record variables by comparing 'fastPeriod' values with 'slowPeriod' values, also applying 'fastBoost' and 'gravity'\n\nvariable.fastPriceRange = variable.smaFastTotalRange\nvariable.slowPriceRange = variable.smaSlowTotalRange\nvariable.longTermPriceRange = variable.smaLongTermRange\n\nvariable.bullPriceDeviation = ((((variable.smaFastBullPriceRange * fastBoost) + (variable.smaSlowBullPriceRange * gravity)) / (gravity + 1)) / variable.slowPriceRange) * 2\n\nvariable.volumeDeviation = variable.smaFastTotalVolume / variable.smaLongTermTotalVolume\n\nvariable.openInterestDeviation = ((((variable.smaFastOpenInterest * fastBoost) + (variable.smaSlowOpenInterest * gravity)) / (gravity + 1)) / variable.smaSlowOpenInterest)\n\nvariable.smaPrice = variable.smaMultipliedFastCandleClose / variable.smaLongTermCandleClose\n\n// Happy trading! CJ.","project":"Superalgos","id":"8c60ba71-a9d3-4f8e-afe0-896444288364","savedPayload":{"position":{"x":12573.245899592053,"y":18466.10349130047},"targetPosition":{"x":12650.96049573775,"y":18529.035530405454},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"a063882c-12d0-4d12-9b5a-ca5b1db72b7f","savedPayload":{"position":{"x":12650.96049573775,"y":18529.035530405454},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"initialization":{"type":"Procedure Initialization","name":"New Procedure Initialization","project":"Superalgos","procedureJavascriptCode":{"type":"Procedure Javascript Code","name":"New Procedure Javascript Code","code":"/* Initialization Code */\n\n// Build 6 arrays \n\nvariable.previousCurrentVolume = []\nvariable.savedTotalRange = []\nvariable.savedBullPriceRange = [] \nvariable.savedTotalVolume = [] \nvariable.savedOpenInterest = [] \nvariable.savedCandleClose = [] ","project":"Superalgos","id":"34d8c2bd-b8fc-4584-9d03-262c2ed57243","savedPayload":{"position":{"x":12677.94040256997,"y":18390.038482438627},"targetPosition":{"x":12713.7771975245,"y":18483.39652508835},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{}}},"id":"7aab7dde-e3ed-45b0-907e-f7e7ca67c900","savedPayload":{"position":{"x":12713.7771975245,"y":18483.39652508835},"targetPosition":{"x":12767.532389956295,"y":18623.43358906293},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"59f62f92-018d-4f53-9c86-efa887cad1ce","savedPayload":{"position":{"x":12767.532389956295,"y":18623.43358906293},"targetPosition":{"x":12943.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"331e099d-5ffe-4d60-8186-effe0aef5d17","savedPayload":{"position":{"x":12943.867965644038,"y":18866.138687375413},"targetPosition":{"x":13243.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Plotter Module","name":"Average VS Average","id":"13acaaae-6a8e-4e48-a326-9d209079629f"}}}],"id":"01b8702d-ee62-45f7-ac01-e1f7ce70c843","savedPayload":{"position":{"x":13243.867965644038,"y":18866.138687375413},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"plotters":[{"type":"Plotter","name":"Chaikin Oscillator Plotter","config":"{\n \"codeName\": \"Chaikin-Oscillator\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Chaikin Oscillator","config":"{\n \"codeName\": \"chaikinOscillator\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.zeroLine","project":"Superalgos","id":"80862799-63a8-4ba6-a807-b8425ebf42e6","savedPayload":{"position":{"x":12437.728644668177,"y":19458.751691732494},"targetPosition":{"x":12390.798305156108,"y":19162.445189553953},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ef40ac92-9977-4887-9c81-b2442254f267","savedPayload":{"position":{"x":12390.798305156108,"y":19162.445189553953},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.zeroLine","project":"Superalgos","id":"926f7d83-fec5-4224-b5a4-8e1a54520950","savedPayload":{"position":{"x":12071.473665800311,"y":19400.742601888433},"targetPosition":{"x":12207.670815722175,"y":19133.440644631923},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47","savedPayload":{"position":{"x":12207.670815722175,"y":19133.440644631923},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.chaikinOscillator","project":"Superalgos","id":"e741c1f0-43b2-4863-8d93-7fc46b343d93","savedPayload":{"position":{"x":11809.264051131018,"y":19138.53298721914},"targetPosition":{"x":12076.566008387528,"y":19002.335837297276},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"53915588-afe8-48a8-9d68-5726ff873676","savedPayload":{"position":{"x":12076.566008387528,"y":19002.335837297276},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Chaikin Oscillator End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.chaikinOscillator","project":"Superalgos","id":"10fc95bd-dc19-407a-809e-6f4f385316f6","savedPayload":{"position":{"x":11751.254961286957,"y":18772.278008351273},"targetPosition":{"x":12047.561463465498,"y":18819.208347863343},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8","savedPayload":{"position":{"x":12047.561463465498,"y":18819.208347863343},"targetPosition":{"x":12343.867965644038,"y":18866.138687375413},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b2a71e98-e51b-4b89-972e-d5581f4625e0","savedPayload":{"position":{"x":12343.867965644038,"y":18866.138687375413},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"246dfad4-544c-47fb-8b84-977bdd41cd47","savedPayload":{"position":{"x":14463.44450422656,"y":16854.484741416603},"targetPosition":{"x":14753.22225211328,"y":16932.13045494736},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8896e73d-ee20-461b-9608-55f4927c4b10","savedPayload":{"position":{"x":14753.22225211328,"y":16932.13045494736},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"163aeab0-ae3e-4467-9da4-9f96dc09ec0f","savedPayload":{"position":{"x":14893.000000000002,"y":16749.968547342785},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"ef40ac92-9977-4887-9c81-b2442254f267"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"e1f60b5e-6727-44d7-8e9c-d913098cd747","savedPayload":{"position":{"x":15120.64571353076,"y":16719.998420591397},"targetPosition":{"x":15043.000000000002,"y":17009.776168478118},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"1b1be8ea-2fa5-41c4-bba0-6ca2139b3f47"}}}],"id":"f79ac980-28be-4eaf-87ee-0ae394c976eb","savedPayload":{"position":{"x":12256.000000000002,"y":18654.00665301945},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"Chaikin Oscillator","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"60001259-de7c-4c30-b752-839c3ec0cd10","savedPayload":{"position":{"x":11743.867965644038,"y":18441.874618663485},"targetPosition":{"x":12043.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7dcea241-9bf6-4dcd-99d5-f568e8ebd151","savedPayload":{"position":{"x":12043.867965644038,"y":18441.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Chaikin Oscillator Begin","project":"Superalgos","id":"9efb3b5e-4eeb-4aa8-a18e-bada560c738f","savedPayload":{"position":{"x":12131.735931288074,"y":18229.74258430752},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator Begin","id":"53915588-afe8-48a8-9d68-5726ff873676"}}},{"type":"Polygon Vertex","name":"Chaikin Oscillator End","project":"Superalgos","id":"08067dd0-d1a3-4b75-bcee-996118cfd9db","savedPayload":{"position":{"x":12343.867965644038,"y":18141.874618663485},"targetPosition":{"x":12343.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Chaikin Oscillator End","id":"56c5b893-e76e-4eae-b3d3-e2bb1c985ad8"}}}],"id":"b5dd57fb-a9cc-48f2-bc06-cb3b02544f08","savedPayload":{"position":{"x":12343.867965644038,"y":18441.874618663485},"targetPosition":{"x":12556.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"d4571993-801c-4a30-9fc9-eac333de1451","savedPayload":{"position":{"x":12556.000000000002,"y":18654.00665301945},"targetPosition":{"x":12856.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"b4b61f3f-b65e-43b2-b8ee-6f87944fb7ae","savedPayload":{"position":{"x":12856.000000000002,"y":18654.00665301945},"targetPosition":{"x":13156.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"9639a20f-b875-46f6-8cbb-4e71cc941041","savedPayload":{"position":{"x":13156.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Slow Plotter","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Slow","config":"{\n \"codeName\": \"slowARPS\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"a210d685-38e1-43a3-9878-adbd61c761e0","savedPayload":{"position":{"x":15538.752452292845,"y":18825.3271911492},"targetPosition":{"x":15238.886722607795,"y":18816.35255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e","savedPayload":{"position":{"x":15238.886722607795,"y":18816.35255129838},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"b884cd0e-265e-4f70-846f-33a37a257ecc","savedPayload":{"position":{"x":15471.572466325475,"y":19083.76338171794},"targetPosition":{"x":15205.296729624106,"y":18945.57064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5","savedPayload":{"position":{"x":15205.296729624106,"y":18945.57064658275},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"eb99829a-5d1a-40e4-9ccc-7fc73d6c6948","savedPayload":{"position":{"x":15298.914129735489,"y":19287.45804025429},"targetPosition":{"x":15118.967561329113,"y":19047.417975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2852ef63-8ffe-4516-b5f9-f635ea773efa","savedPayload":{"position":{"x":15118.967561329113,"y":19047.417975850924},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"8aedf7aa-675e-467b-b9b5-d60754399725","savedPayload":{"position":{"x":15054.974543600074,"y":19396.066941484063},"targetPosition":{"x":14996.997768261406,"y":19101.72242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"66be2c9a-b271-4410-b305-d6ff7a8f6806","savedPayload":{"position":{"x":14996.997768261406,"y":19101.72242646581},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"4db679ee-e6b7-43e0-89b9-df275970ab75","savedPayload":{"position":{"x":14788.068934676035,"y":19388.07876051796},"targetPosition":{"x":14863.544963799388,"y":19097.728335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31","savedPayload":{"position":{"x":14863.544963799388,"y":19097.728335982767},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"f68cafa6-18dd-40b8-b669-265897ffbbc7","savedPayload":{"position":{"x":14551.061232193262,"y":19265.075654564916},"targetPosition":{"x":14745.041112558001,"y":19036.226783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e","savedPayload":{"position":{"x":14745.041112558001,"y":19036.226783006245},"targetPosition":{"x":14939.02099292274,"y":18807.37791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"0fbe8beb-9d62-46b2-9d77-9b246aff6bdc","savedPayload":{"position":{"x":12634.447798537763,"y":18587.46242578744},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95265ad5-3c49-4d1f-9a60-01bcdf2816be","savedPayload":{"position":{"x":15081.40991376369,"y":19329.96089514218},"targetPosition":{"x":14918.01820325918,"y":19078.359724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d3facbf8-a2e6-4452-b21b-35352511a827","savedPayload":{"position":{"x":14918.01820325918,"y":19078.359724758553},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"36c97105-26c3-475e-949d-ce8c3480f651","savedPayload":{"position":{"x":14692.252985509345,"y":19120.202834595064},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"6c0d2a1f-25f3-4d72-a57d-97f2c956f40e"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"6dd790c5-abf3-4fb3-b19f-6afaf91da40a","savedPayload":{"position":{"x":14503.025322371046,"y":18990.15026487943},"targetPosition":{"x":14754.626492754673,"y":18826.758554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"ae39d4c5-612d-4ac3-a447-2c3157e028e5"}}}],"id":"c92be7eb-fddc-4bc6-a65d-a0a40bc37ec8","savedPayload":{"position":{"x":12490.357013017727,"y":18470.780008342786},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"95ed4962-8fe8-4f35-ae47-64204481b727","savedPayload":{"position":{"x":14562.654978611015,"y":19333.231176915182},"targetPosition":{"x":14578.355765483899,"y":19033.642316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"e7445d37-5968-48de-927c-4efdb45b7c59","savedPayload":{"position":{"x":14578.355765483899,"y":19033.642316488807},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"0f784377-cb5c-4f2f-96b3-68407b05af78","savedPayload":{"position":{"x":14371.113104713564,"y":18934.7926379701},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"2852ef63-8ffe-4516-b5f9-f635ea773efa"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"8c0f843b-249e-4a35-88b9-70f63e1890c3","savedPayload":{"position":{"x":14294.46769193041,"y":18718.352669189557},"targetPosition":{"x":14594.056552356782,"y":18734.05345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"66be2c9a-b271-4410-b305-d6ff7a8f6806"}}}],"id":"f019e42a-3005-4a2b-9717-48d6902c03da","savedPayload":{"position":{"x":12442.36932297498,"y":18291.687510965396},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"b3ea885c-fc4e-44b5-93e4-c965b7622d6d","savedPayload":{"position":{"x":14141.051196759618,"y":19030.96039000926},"targetPosition":{"x":14329.847314074568,"y":18797.81660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"a1fa021f-4b0f-41ee-a344-cdb8360b641a","savedPayload":{"position":{"x":14329.847314074568,"y":18797.81660157217},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"1c703412-aa66-4f3c-953e-f1798935a713","savedPayload":{"position":{"x":14220.286862779038,"y":18596.031352115377},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"8a80a7ec-3ffd-4d5f-b212-b5e052515b31"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"e915dba3-f07e-42df-9705-7da67057decd","savedPayload":{"position":{"x":14285.499642952427,"y":18375.876695820127},"targetPosition":{"x":14518.643431389519,"y":18564.67281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"bc3e9257-c56b-42ef-a0cb-82656d0a364e"}}}],"id":"07d9669b-ce23-49fb-b2dd-666c5f32c755","savedPayload":{"position":{"x":12508.814394964262,"y":18118.592180523327},"targetPosition":{"x":12741.958183401353,"y":18307.38829783828},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"59717ffa-8d07-4e2b-98da-e6fb3353ea04","savedPayload":{"position":{"x":12741.958183401353,"y":18307.38829783828},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Slow","config":"{\n \"codeName\": \"ARPS-Slow\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"6f7acaa5-1243-4f77-875f-5397475358e9","savedPayload":{"position":{"x":12699.574023683499,"y":17530.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c1de33b9-fa92-419f-baa8-081dc437c569","savedPayload":{"position":{"x":12959.38164481883,"y":17380.157215285468},"targetPosition":{"x":12959.38164481883,"y":17680.157215285468},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"8fd22998-6471-490b-bd96-9d30d99978b8","savedPayload":{"position":{"x":12959.38164481883,"y":17680.157215285468},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"20fc3099-2c91-4c55-9336-60553f207253","savedPayload":{"position":{"x":13109.38164481883,"y":17360.40934064736},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"6906425e-38ab-4aaa-84da-b4e43eda38cd","savedPayload":{"position":{"x":13399.15939270555,"y":17438.055054178116},"targetPosition":{"x":13187.027358349585,"y":17650.18708853408},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b9bd72d6-fe20-411e-a481-3593020f9ee2","savedPayload":{"position":{"x":13187.027358349585,"y":17650.18708853408},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"457c2cc9-cf06-407d-a12b-e9a24ce43a3b","savedPayload":{"position":{"x":13519.18926595416,"y":17530.157215285468},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"8d54d8bf-89eb-41f8-bfb2-8a471506b3b5","savedPayload":{"position":{"x":13669.18926595416,"y":17789.9648364208},"targetPosition":{"x":13369.18926595416,"y":17789.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2731ea97-36e9-4bad-8339-803c567e8a87","savedPayload":{"position":{"x":13369.18926595416,"y":17789.9648364208},"targetPosition":{"x":13109.38164481883,"y":17939.9648364208},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"75e49a63-45a5-4f16-876e-53a509ddb245","savedPayload":{"position":{"x":13109.38164481883,"y":17939.9648364208},"targetPosition":{"x":13031.735931288074,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e12e90bd-bc37-42da-9f83-7b1506391bd9","savedPayload":{"position":{"x":13031.735931288074,"y":18229.74258430752},"targetPosition":{"x":13243.867965644038,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f3a68e45-18b6-4192-bccd-00364c5d72c0","savedPayload":{"position":{"x":13243.867965644038,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"ARPS Fast Plotter","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"SMA Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.SMA","project":"Superalgos","id":"7f32a7cc-bbbb-4b76-918d-fb4b49ae1cbe","savedPayload":{"position":{"x":15614.752452292845,"y":18600.8271911492},"targetPosition":{"x":15314.886722607795,"y":18591.85255129838},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"43c595ce-8ba1-4a6a-b126-38898e46c880","savedPayload":{"position":{"x":15314.886722607795,"y":18591.85255129838},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"SMA End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.SMA","project":"Superalgos","id":"17b6dd00-6205-482f-8ed4-1c7b215aa634","savedPayload":{"position":{"x":15547.572466325475,"y":18859.26338171794},"targetPosition":{"x":15281.296729624106,"y":18721.07064658275},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d","savedPayload":{"position":{"x":15281.296729624106,"y":18721.07064658275},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBull","project":"Superalgos","id":"c65449b6-1047-449c-8974-d439b263f767","savedPayload":{"position":{"x":15374.914129735489,"y":19062.95804025429},"targetPosition":{"x":15194.967561329117,"y":18822.917975850924},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade","savedPayload":{"position":{"x":15194.967561329117,"y":18822.917975850924},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bull End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBull","project":"Superalgos","id":"bf788df7-d7bd-44f5-a1e2-f991b559eb67","savedPayload":{"position":{"x":15130.974543600076,"y":19171.566941484063},"targetPosition":{"x":15072.997768261408,"y":18877.22242646581},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58","savedPayload":{"position":{"x":15072.997768261408,"y":18877.22242646581},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.apsBear","project":"Superalgos","id":"e4644710-8f0c-462d-b981-a1dce5b8c73a","savedPayload":{"position":{"x":14864.068934676037,"y":19163.57876051796},"targetPosition":{"x":14939.54496379939,"y":18873.228335982767},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a144fd80-7187-4237-8a1e-efc6927eb58f","savedPayload":{"position":{"x":14939.54496379939,"y":18873.228335982767},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"APS Bear End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.apsBear","project":"Superalgos","id":"c31177a2-ed80-4eab-9b17-b4a6a17fd77a","savedPayload":{"position":{"x":14627.061232193264,"y":19040.575654564916},"targetPosition":{"x":14821.041112558003,"y":18811.726783006245},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"725734c1-1636-4802-a3d7-40caa4b4f655","savedPayload":{"position":{"x":14821.041112558003,"y":18811.726783006245},"targetPosition":{"x":15015.020992922742,"y":18582.87791144756},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"ddc7e432-cf87-475e-8af1-ddd2209fde78","savedPayload":{"position":{"x":12922.12874157189,"y":18026.027645942188},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"SMA","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 2,\n 2\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"25a3b187-cb00-4569-881a-e8599a2ac9bf","savedPayload":{"position":{"x":15157.40991376369,"y":19105.46089514218},"targetPosition":{"x":14994.018203259182,"y":18853.859724758553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"7807b9a3-05ea-421c-8584-d363dff6ca7a","savedPayload":{"position":{"x":14994.018203259182,"y":18853.859724758553},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"SMA Begin","project":"Superalgos","id":"498ac6aa-2b55-4793-b2fe-0fd647ae7512","savedPayload":{"position":{"x":14768.252985509347,"y":18895.702834595064},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA Begin","id":"43c595ce-8ba1-4a6a-b126-38898e46c880"}}},{"type":"Polygon Vertex","name":"SMA End","project":"Superalgos","id":"f65fd57b-fd01-440e-a825-098fff6c4952","savedPayload":{"position":{"x":14579.025322371048,"y":18765.65026487943},"targetPosition":{"x":14830.626492754674,"y":18602.258554374926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"SMA End","id":"547e8e7d-b5b6-4fcd-ba52-975447186c6d"}}}],"id":"d481800e-4a37-4638-a095-e03282974b8d","savedPayload":{"position":{"x":12902.74809864453,"y":17841.63314577412},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bull","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed TURQUOISE","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"8463545a-e7e6-46d1-975c-729f23eaa7d2","savedPayload":{"position":{"x":14638.654978611017,"y":19108.731176915182},"targetPosition":{"x":14654.3557654839,"y":18809.142316488807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"0fbd4479-d451-4f8a-8452-27171db16d82","savedPayload":{"position":{"x":14654.3557654839,"y":18809.142316488807},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bull Begin","project":"Superalgos","id":"63eacfe5-505a-4634-bb5e-c63214b48ebd","savedPayload":{"position":{"x":14447.113104713566,"y":18710.2926379701},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull Begin","id":"ec943efd-adb7-4d6a-8bab-1f77dae8bade"}}},{"type":"Polygon Vertex","name":"APS Bull End","project":"Superalgos","id":"eed08a75-d991-4dd6-98d1-6e0ee70dd04e","savedPayload":{"position":{"x":14370.467691930411,"y":18493.852669189557},"targetPosition":{"x":14670.056552356784,"y":18509.55345606244},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bull End","id":"a8a9bc4f-6b37-4ce7-8e87-0589fcf5fb58"}}}],"id":"3bfca508-8cbb-4bad-8473-b0e8d785069e","savedPayload":{"position":{"x":12995.453196957013,"y":17681.06320537623},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"APS Bear","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"Dashed RED","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"a280c06f-5e9c-44b4-906c-0bd88866c1e4","savedPayload":{"position":{"x":14217.05119675962,"y":18806.46039000926},"targetPosition":{"x":14405.84731407457,"y":18573.31660157217},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"ff24e3b0-c186-4d2b-8722-e19f72075d41","savedPayload":{"position":{"x":14405.84731407457,"y":18573.31660157217},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"APS Bear Begin","project":"Superalgos","id":"cffa95e0-222b-46da-b1db-5ca83d0dc237","savedPayload":{"position":{"x":14296.28686277904,"y":18371.531352115377},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear Begin","id":"a144fd80-7187-4237-8a1e-efc6927eb58f"}}},{"type":"Polygon Vertex","name":"APS Bear End","project":"Superalgos","id":"adc73235-49b3-4e74-a451-0a4ba69e0547","savedPayload":{"position":{"x":14361.499642952429,"y":18151.376695820127},"targetPosition":{"x":14594.64343138952,"y":18340.17281313508},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"APS Bear End","id":"725734c1-1636-4802-a3d7-40caa4b4f655"}}}],"id":"c6488672-2e9b-43a6-b6de-a398ea651320","savedPayload":{"position":{"x":13164.833839884375,"y":17605.650084408968},"targetPosition":{"x":13196.19237886467,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"4ff7b240-bdd0-4f1d-8e31-5f9084686c69","savedPayload":{"position":{"x":13196.19237886467,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[{"type":"Plotter Panel","name":"ARPS Fast","config":"{\n \"codeName\": \"ARPS-Fast\"\n}","project":"Superalgos","panelData":[{"type":"Panel Data","name":"Average Range % per Candle","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageARPS","project":"Superalgos","id":"4fae804c-e7d9-4f8f-9441-59e26185fff7","savedPayload":{"position":{"x":13715.807621135333,"y":17324.451157246007},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.BLACK\"\n}","project":"Superalgos","id":"c5312c7b-f55e-43b7-943e-902588c25c9b","savedPayload":{"position":{"x":14005.585369022052,"y":17402.096870776764},"targetPosition":{"x":13793.453334666088,"y":17614.228905132728},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"cdda2164-3e6b-4817-acbc-891388443917","savedPayload":{"position":{"x":13793.453334666088,"y":17614.228905132728},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BULL","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBull","project":"Superalgos","id":"b9258e5a-1bef-4144-b489-3a65a5c867af","savedPayload":{"position":{"x":14125.615242270664,"y":17494.199031884116},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n \"paletteColor\": \"UI_COLOR.PATINATED_TURQUOISE\"\n}","project":"Superalgos","id":"9a9c7c68-f24e-4c5e-9e29-34b8260df057","savedPayload":{"position":{"x":14275.615242270664,"y":17754.00665301945},"targetPosition":{"x":13975.615242270664,"y":17754.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"2ce1a18f-aa45-4b1e-a01b-2125ebf93c8e","savedPayload":{"position":{"x":13975.615242270664,"y":17754.00665301945},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Panel Data","name":"Average % BEAR","config":"{\n \"valueDecimals\": 2\n}","project":"Superalgos","dataFormula":{"type":"Data Formula","name":"New Data Formula","code":"record.percentageApsBear","project":"Superalgos","id":"ea88a867-d92e-4680-a40b-ec580bd80df2","savedPayload":{"position":{"x":14295.363116908775,"y":17904.00665301945},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"textStyle":{"type":"Text Style","name":"New Text Style","config":"{\n\"paletteColor\": \"UI_COLOR.RED\"\n}","project":"Superalgos","id":"6430bee3-15e0-4598-a686-2ebc5f4ec6f5","savedPayload":{"position":{"x":14217.717403378017,"y":18193.78440090617},"targetPosition":{"x":14005.585369022054,"y":17981.652366550206},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"39efdc4e-0784-48c0-a39b-0dc54548cb77","savedPayload":{"position":{"x":14005.585369022054,"y":17981.652366550206},"targetPosition":{"x":13715.807621135333,"y":17904.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"775abeea-a292-46a5-aebb-f8c0bfef7ca0","savedPayload":{"position":{"x":13715.807621135333,"y":17904.00665301945},"targetPosition":{"x":13456.000000000002,"y":18054.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"fdffbdff-a42f-47db-b068-4a711070bef3","savedPayload":{"position":{"x":13456.000000000002,"y":18054.00665301945},"targetPosition":{"x":13456.000000000002,"y":18354.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"5a1c468b-1e45-414b-8710-952a78fe831c","savedPayload":{"position":{"x":13456.000000000002,"y":18354.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Plotter","name":"Average VS Average Plotter","config":"{\n \"codeName\": \"averageVsAverage\"\n}","project":"Superalgos","modules":[{"type":"Plotter Module","name":"Average VS Average","config":"{\n \"codeName\": \"averageVsAverage\",\n \"icon\": \"oscillator\"\n}","project":"Superalgos","shapes":{"type":"Shapes","name":"New Shapes","project":"Superalgos","chartPoints":[{"type":"Chart Points","name":"New Chart Points","project":"Superalgos","points":[{"type":"Point","name":"Zero Line Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = 1","project":"Superalgos","id":"80edad17-0f41-4dbb-864e-c2b257b06dde","savedPayload":{"position":{"x":13012.422735946908,"y":17744.918604065882},"targetPosition":{"x":13457.320310615743,"y":17677.345324925474},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"c695315b-a12a-4972-8363-a3812215a54e","savedPayload":{"position":{"x":13457.320310615743,"y":17677.345324925474},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"Zero Line End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = 1","project":"Superalgos","id":"bf6adc6e-9aaf-434a-a41d-12a97f076653","savedPayload":{"position":{"x":13010.390506126048,"y":17488.75995637569},"targetPosition":{"x":13456.304195705314,"y":17549.266001080377},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c","savedPayload":{"position":{"x":13456.304195705314,"y":17549.266001080377},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.bullPriceDeviation","project":"Superalgos","id":"52a0dcca-d50d-4dfa-adb0-d6a2d2593187","savedPayload":{"position":{"x":13080.608826662963,"y":17242.404988482835},"targetPosition":{"x":13491.413355973771,"y":17426.08851713395},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf","savedPayload":{"position":{"x":13491.413355973771,"y":17426.08851713395},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"bullPriceDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.bullPriceDeviation","project":"Superalgos","id":"18676f64-51d5-4480-8ca7-398a8cf45098","savedPayload":{"position":{"x":13217.389026832188,"y":17025.81191475659},"targetPosition":{"x":13559.803456058384,"y":17317.791980270827},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f","savedPayload":{"position":{"x":13559.803456058384,"y":17317.791980270827},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.volumeDeviation","project":"Superalgos","id":"9cf7a19a-ff50-46ca-86c3-f8412d4e53ee","savedPayload":{"position":{"x":13409.64998827918,"y":16856.527817901653},"targetPosition":{"x":13655.93393678188,"y":17233.14993184336},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19","savedPayload":{"position":{"x":13655.93393678188,"y":17233.14993184336},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"volumeDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.volumeDeviation","project":"Superalgos","id":"c14b45db-6a55-4b02-83d3-f9c758bcdbde","savedPayload":{"position":{"x":13641.815871327472,"y":16748.267088673914},"targetPosition":{"x":13772.016878306025,"y":17179.01956722949},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82","savedPayload":{"position":{"x":13772.016878306025,"y":17179.01956722949},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.openInterestDeviation","project":"Superalgos","id":"afc254ff-402b-4632-952a-3a8504eb2f11","savedPayload":{"position":{"x":13895.07797687616,"y":16709.800367504067},"targetPosition":{"x":13898.64793108037,"y":17159.786206644567},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"803aaa7c-ad01-4bad-9943-f4fac99e4987","savedPayload":{"position":{"x":13898.64793108037,"y":17159.786206644567},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"openInterestDeviation End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.openInterestDeviation","project":"Superalgos","id":"2d21a7f4-e6ea-47c2-85ec-4638fd68d0bd","savedPayload":{"position":{"x":14148.91851534143,"y":16744.243999370883},"targetPosition":{"x":14025.568200313004,"y":17177.008022577975},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2","savedPayload":{"position":{"x":14025.568200313004,"y":17177.008022577975},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice Begin","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.begin\ny = record.previous.smaPrice","project":"Superalgos","id":"d2a3c177-7426-4111-9e6e-80bd2ddd2ecc","savedPayload":{"position":{"x":14382.77283594463,"y":16848.80756606468},"targetPosition":{"x":14142.495360614605,"y":17229.289805924873},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"de30fcce-febc-4c65-8908-852b2c91a3d9","savedPayload":{"position":{"x":14142.495360614605,"y":17229.289805924873},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Point","name":"smaPrice End","project":"Superalgos","pointFormula":{"type":"Point Formula","name":"New Point Formula","code":"x = record.end\ny = record.smaPrice","project":"Superalgos","id":"0bfdd80f-4420-4333-a60e-ac5afe17df21","savedPayload":{"position":{"x":14577.695452415694,"y":17015.01994927541},"targetPosition":{"x":14239.956668850136,"y":17312.39599753024},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2","savedPayload":{"position":{"x":14239.956668850136,"y":17312.39599753024},"targetPosition":{"x":13902.21788528458,"y":17609.772045785066},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"f20cacf7-c7ce-4a35-a06d-15951850e570","savedPayload":{"position":{"x":13902.21788528458,"y":17609.772045785066},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":4,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"polygons":[{"type":"Polygon","name":"Zero Line","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.75,\n \"lineWidth\": 0.75,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.75,\n \"lineWidth\": 1.5,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.TITANIUM_YELLOW\"\n }\n}","project":"Superalgos","id":"62cd1b53-a0fd-4f09-a9c0-9bb7ac3ac642","savedPayload":{"position":{"x":13606.622714372208,"y":17333.07957471211},"targetPosition":{"x":13836.436047307901,"y":17525.91585761807},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"8eca09c2-69dc-4768-b3e4-08fa7f68b8e6","savedPayload":{"position":{"x":13836.436047307901,"y":17525.91585761807},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"af6872e7-8d5d-451e-802c-de5f614ea534","savedPayload":{"position":{"x":14040.102657419297,"y":17419.89373109651},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"9bfa8714-fe8d-4631-b9ca-8236b9f989b7","savedPayload":{"position":{"x":14259.085663149557,"y":17488.93880758834},"targetPosition":{"x":14066.249380243595,"y":17718.752140524033},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}}],"id":"ed0185c6-e131-4acf-983c-8ddfe5f1c523","savedPayload":{"position":{"x":14066.249380243595,"y":17718.752140524033},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice > record.previous.smaPrice","project":"Superalgos","id":"6f7dcb6c-ae19-46b2-a082-916dae93a16b","savedPayload":{"position":{"x":14003.00510583763,"y":16806.807443877766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"5860dc00-e1a5-4c65-bd4e-843091d935ce","savedPayload":{"position":{"x":13702.103077599852,"y":16642.91315569686},"targetPosition":{"x":13998.409579778392,"y":16689.843495208926},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"675151a8-9c7d-4c48-860d-00e52056eec5","savedPayload":{"position":{"x":13998.409579778392,"y":16689.843495208926},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bf8ec324-5a02-4895-80ac-46fd519aa77c","savedPayload":{"position":{"x":13783.131983344476,"y":16423.274695891418},"targetPosition":{"x":14038.924032650704,"y":16580.024265306205},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f7367289-76e5-48d5-a910-0c6636e8869c","savedPayload":{"position":{"x":14038.924032650704,"y":16580.024265306205},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"a74fa0b1-3291-4e48-a1e2-6fed290b521e","savedPayload":{"position":{"x":14118.38050626919,"y":16494.068736408506},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"33d6f2c5-3db4-42ce-8766-f408840b78e0","savedPayload":{"position":{"x":14224.682472800161,"y":16445.062858601686},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8ca3ff70-71b8-41a7-b184-2d85d95c29f4","savedPayload":{"position":{"x":14341.646421469002,"y":16440.46733254245},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"b711c638-8290-4d76-a1f4-96a9019c6b3d","savedPayload":{"position":{"x":14451.465651371718,"y":16480.981785414766},"targetPosition":{"x":14294.716081956933,"y":16736.773834720992},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"a7e542dd-3221-4a1a-ab83-16a44d001416","savedPayload":{"position":{"x":14170.041816598648,"y":17727.832802064837},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"smaPrice BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.smaPrice < record.previous.smaPrice","project":"Superalgos","id":"da6fa977-095e-439d-90a2-7e226c210bd1","savedPayload":{"position":{"x":14090.2888941966,"y":16657.139460121613},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.8,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 1,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"9e2a011a-4aa8-463c-a10c-dd18e0534a50","savedPayload":{"position":{"x":13863.588626615938,"y":16400.214652104183},"targetPosition":{"x":14125.974538757757,"y":16545.657538178082},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"d395d4a9-883b-49e9-90ae-a83f2fe2f59d","savedPayload":{"position":{"x":14125.974538757757,"y":16545.657538178082},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"941bac99-ea7f-4f0f-b149-3cf34f766cb0","savedPayload":{"position":{"x":14014.851668917005,"y":16221.535530140533},"targetPosition":{"x":14201.60605990829,"y":16456.317977196257},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"2ce85b80-0291-4b52-a297-72dd5e780d6e","savedPayload":{"position":{"x":14201.60605990829,"y":16456.317977196257},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"smaPrice Begin","project":"Superalgos","id":"775e669a-6800-4190-9cad-dbae717911f5","savedPayload":{"position":{"x":14305.669244154476,"y":16402.721915470484},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice Begin","id":"de30fcce-febc-4c65-8908-852b2c91a3d9"}}},{"type":"Polygon Vertex","name":"smaPrice End","project":"Superalgos","id":"0a680163-5643-4a13-b55b-5fb80edde733","savedPayload":{"position":{"x":14422.321415029948,"y":16393.028867549005},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"smaPrice End","id":"34af7c63-1865-42ac-b0f3-1ae31470bcd2"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"cb32f3a6-681d-4df5-bdfc-14270081099b","savedPayload":{"position":{"x":14533.803336973477,"y":16428.71451211016},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"e50f0167-e004-4f8a-b593-1729a14e7c0d","savedPayload":{"position":{"x":14623.1428979553,"y":16504.346033260696},"targetPosition":{"x":14388.360450899576,"y":16691.10042425198},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}}],"id":"57807fe3-2d38-4767-8cee-b0d9091d358e","savedPayload":{"position":{"x":14264.469033973206,"y":17771.86493666486},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation ABOVE","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation > record.previous.volumeDeviation","project":"Superalgos","id":"5579428b-bd6e-44f1-b53a-9b9b9948b091","savedPayload":{"position":{"x":14231.426213757817,"y":16531.507148561304},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"bbe1b239-e08b-440e-971a-49c3ee92a19a","savedPayload":{"position":{"x":14151.518676912645,"y":16186.158059796802},"targetPosition":{"x":14321.74863834028,"y":16433.183888876167},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"826e811a-3650-45c8-914d-b9cdb25c7624","savedPayload":{"position":{"x":14321.74863834028,"y":16433.183888876167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"4393fca4-e15d-4170-a127-5862e8c845a2","savedPayload":{"position":{"x":14445.787194516954,"y":16383.787124213184},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"8c390826-ef92-470f-bd4f-4fb5aa2995a6","savedPayload":{"position":{"x":14578.97452500399,"y":16393.100489625405},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"aa9b0281-5501-4ecf-8747-03df65df1b82","savedPayload":{"position":{"x":14694.931245563015,"y":16459.27935887202},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"114e6dce-ec3c-4ab1-b7f4-5f72f36eeabb","savedPayload":{"position":{"x":14770.690705571464,"y":16569.216195268167},"targetPosition":{"x":14491.978599767914,"y":16680.20971795553},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"d42bf0ab-d03e-4a30-a896-d27fdbe4fa98","savedPayload":{"position":{"x":14338.14171635459,"y":17845.537619046245},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"volumeDeviation BELOW","project":"Superalgos","polygonCondition":{"type":"Polygon Condition","name":"New Polygon Condition","code":"record.volumeDeviation < record.previous.volumeDeviation","project":"Superalgos","id":"ba7ccc38-7438-4fd9-8d17-1f7d1c4bff39","savedPayload":{"position":{"x":14157.277178666109,"y":16579.923368208143},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonBody":{"type":"Polygon Body","name":"New Polygon Body","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 0.2,\n \"paletteColor\": \"UI_COLOR.RED\"\n },\n \"atMousePosition\": {\n \"opacity\": 0.3,\n \"paletteColor\": \"UI_COLOR.RED\"\n }\n}","project":"Superalgos","id":"43749c18-0468-43de-9198-abb8d04541dc","savedPayload":{"position":{"x":14018.614376933985,"y":16253.69670625219},"targetPosition":{"x":14229.153747799182,"y":16467.409535337592},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"1c2a8a8c-9619-43e6-b564-f478e699a656","savedPayload":{"position":{"x":14229.153747799182,"y":16467.409535337592},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"Zero Line Begin","project":"Superalgos","id":"564d9677-fff2-429f-8dd1-61233ab23d60","savedPayload":{"position":{"x":14342.73022142804,"y":16397.224149283244},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line Begin","id":"c695315b-a12a-4972-8363-a3812215a54e"}}},{"type":"Polygon Vertex","name":"Zero Line End","project":"Superalgos","id":"7aacc15f-eba7-4455-a74a-23ba60467128","savedPayload":{"position":{"x":14475.511386026454,"y":16383.268286520444},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"Zero Line End","id":"d04e0d03-bea6-4066-8fc8-9a2118673f3c"}}},{"type":"Polygon Vertex","name":"volumeDeviation End","project":"Superalgos","id":"9b74661e-c05a-4407-9e2d-f387f2b439e2","savedPayload":{"position":{"x":14601.198303491585,"y":16428.30607682678},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation End","id":"1f191bf6-5495-4b78-bc8b-d3492eeeac82"}}},{"type":"Polygon Vertex","name":"volumeDeviation Begin","project":"Superalgos","id":"478698e3-2c63-421d-b25c-bd6e641d76a2","savedPayload":{"position":{"x":14694.897138370581,"y":16523.417233479846},"targetPosition":{"x":14439.69311866438,"y":16681.122364422994},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"volumeDeviation Begin","id":"5af1c2a5-1647-4e38-89e5-7aad7b393e19"}}}],"id":"fb723dee-63a8-46c2-afc4-48210897864c","savedPayload":{"position":{"x":14382.173850954614,"y":17939.9648364208},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"openInterestDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 1,\n \"lineDash\": [\n 2,\n 7\n ],\n \"paletteColor\": \"UI_COLOR.GREY\"\n }\n}","project":"Superalgos","id":"30cdd628-da04-4589-b126-db7da41f9b45","savedPayload":{"position":{"x":14668.977724920003,"y":16163.768375838048},"targetPosition":{"x":14674.213446851189,"y":16463.722684384968},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"5ea53d11-e359-484f-920c-76c642c44018","savedPayload":{"position":{"x":14674.213446851189,"y":16463.722684384968},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"openInterestDeviation Begin","project":"Superalgos","id":"39e8c351-78ce-4df3-abd0-24512243c73a","savedPayload":{"position":{"x":14887.846679920072,"y":16547.875052830295},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation Begin","id":"803aaa7c-ad01-4bad-9943-f4fac99e4987"}}},{"type":"Polygon Vertex","name":"openInterestDeviation End","project":"Superalgos","id":"b4b2a034-19f0-4069-bb3b-dedf524bb993","savedPayload":{"position":{"x":14979.403477329291,"y":16758.441271000705},"targetPosition":{"x":14679.449168782374,"y":16763.676992931887},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"openInterestDeviation End","id":"f36c3390-5e84-428f-aa54-cf2079ac9bf2"}}}],"id":"b38a785b-70da-4d5c-bf56-064fcc5d55b8","savedPayload":{"position":{"x":14391.254512495416,"y":18043.757272775856},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Polygon","name":"bullPriceDeviation","project":"Superalgos","polygonBorder":{"type":"Polygon Border","name":"New Polygon Border","project":"Superalgos","style":{"type":"Style","name":"New Style","config":"{\n \"default\": {\n \"opacity\": 1,\n \"lineWidth\": 3,\n \"lineDash\": [\n 0,\n 0\n ],\n \"paletteColor\": \"UI_COLOR.GREEN\"\n }\n}","project":"Superalgos","id":"345cc144-aed2-4aaf-9e5d-8a9e628704a2","savedPayload":{"position":{"x":14936.030764208717,"y":16280.656443637166},"targetPosition":{"x":14838.360317871571,"y":16564.312016316962},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"styleConditions":[],"id":"f0e9511b-24df-4a07-90df-78bed13778e0","savedPayload":{"position":{"x":14838.360317871571,"y":16564.312016316962},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"polygonVertexes":[{"type":"Polygon Vertex","name":"bullPriceDeviation Begin","project":"Superalgos","id":"6c8f60ee-9ee0-4a0f-bf00-1519a8ba31ec","savedPayload":{"position":{"x":15010.328085424175,"y":16716.456244960038},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation Begin","id":"6f6d60df-e373-4466-aa66-c50b8fd02fcf"}}},{"type":"Polygon Vertex","name":"bullPriceDeviation End","project":"Superalgos","id":"31202df8-551d-48cb-87ee-a782dc2fd278","savedPayload":{"position":{"x":15024.34544421422,"y":16945.63803533391},"targetPosition":{"x":14740.689871534425,"y":16847.96758899676},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Point","name":"bullPriceDeviation End","id":"6c51371f-dc06-43ae-b87f-6c3966f95f5f"}}}],"id":"137e3254-785f-4469-84f6-b654b34fe6b5","savedPayload":{"position":{"x":14364.288439178888,"y":18144.39602847377},"targetPosition":{"x":14092.396103067893,"y":18017.610549951558},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"images":[],"texts":[],"id":"33e571bd-9a26-4e88-8427-5b863d0aed70","savedPayload":{"position":{"x":14092.396103067893,"y":18017.610549951558},"targetPosition":{"x":13880.26406871193,"y":18229.74258430752},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"panels":[],"id":"13acaaae-6a8e-4e48-a326-9d209079629f","savedPayload":{"position":{"x":13880.26406871193,"y":18229.74258430752},"targetPosition":{"x":13668.132034355966,"y":18441.874618663485},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"3548ecec-25e1-4bb8-86c5-9743052bd80b","savedPayload":{"position":{"x":13668.132034355966,"y":18441.874618663485},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"b4f0c498-27c5-4c28-acef-67ff7f317e38","savedPayload":{"position":{"x":13456.000000000002,"y":18654.00665301945},"targetPosition":{"x":13456.000000000002,"y":18654.00665301945},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}} \ No newline at end of file From 194ee13778e58fb335ae4edba7da12acb881aca6 Mon Sep 17 00:00:00 2001 From: 0xperez Date: Sat, 10 Apr 2021 14:46:38 +0200 Subject: [PATCH 20/32] Translating the Welcome Tutorial - Page 58 to 62 --- ...ial-step-visual-scripting-on-steroids.json | 36 +++++++++++++++-- ...lgos-059-tutorial-step-plotters-magic.json | 27 +++++++++++-- ...60-tutorial-step-lets-do-some-testing.json | 36 +++++++++++++++-- ...-061-tutorial-step-aim-high-trade-big.json | 36 +++++++++++++++-- ...-062-tutorial-step-machines-learn-too.json | 40 ++++++++++++++++--- 5 files changed, 154 insertions(+), 21 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-058-tutorial-step-visual-scripting-on-steroids.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-058-tutorial-step-visual-scripting-on-steroids.json index d97a59324..c7a977c4e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-058-tutorial-step-visual-scripting-on-steroids.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-058-tutorial-step-visual-scripting-on-steroids.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "indicator-bot" }, - "text": "Talking about block-building, we are now in the confines of the Masters Data Mine. To your left, the definition of one of the bots you sent mining minutes ago." + "text": "Talking about block-building, we are now in the confines of the Masters Data Mine. To your left, the definition of one of the bots you sent mining minutes ago.", + "translations": [ + { + "language": "IT", + "text": "A proposito di costruzioni a blocchi, ora siamo nei confini del Masters Data Mine. Alla tua sinistra vedi la definizione di uno dei bots per cui hai avviato il mining giusto prima.", + "updated": 1618056284204 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "Pretty much like with the Lego-like definitions of the Charting Space, bots are too defined on a visual environment." + "text": "Pretty much like with the Lego-like definitions of the Charting Space, bots are too defined on a visual environment.", + "translations": [ + { + "language": "IT", + "text": "Analogamente alle dinamiche \"stile Lego\" del Charting Space, anche i bots sono definiti visivamente.", + "updated": 1618056303696 + } + ] }, { "style": "Callout", - "text": "All developers need to code is the actual Data Building Procedure." + "text": "All developers need to code is the actual Data Building Procedure.", + "translations": [ + { + "language": "IT", + "text": "Tutto ciò che gli sviluppatori devono programmare è la Data Building Procedure che verrà usata.", + "updated": 1618056067442 + } + ] }, { "style": "Text", - "text": "Everything else is defined on a visual setting: processes with their dependencies, outputs and so on, and products, with their record and dataset definitions, etc." + "text": "Everything else is defined on a visual setting: processes with their dependencies, outputs and so on, and products, with their record and dataset definitions, etc.", + "translations": [ + { + "language": "IT", + "text": "Ogni cosa ha una rappresentazione visiva: sia i processi, con le loro dipendenze e output, che i prodotti, con i loro record e datasets, così come ogni altra entità presente nel programma.", + "updated": 1618056262610 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-059-tutorial-step-plotters-magic.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-059-tutorial-step-plotters-magic.json index 5373f3a72..068791b4c 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-059-tutorial-step-plotters-magic.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-059-tutorial-step-plotters-magic.json @@ -7,17 +7,38 @@ "project": "Superalgos", "name": "plotter" }, - "text": "And this is how plotters are built! Plotters create graphical representations of data... from candles, to everything else!" + "text": "And this is how plotters are built! Plotters create graphical representations of data... from candles, to everything else!", + "translations": [ + { + "language": "IT", + "text": "Ed ecco come vengono costruiti i Plotters! Essi creano rappresentazioni grafiche di tutti i dati...dalle candele, a qualsiasi altra cosa!", + "updated": 1618056813296 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "Again, visual scripting at its best! Plotters use stylized polygons made out of coordinate points to paint lines and shapes that represent data. Every layer made available on the charts is created with a set of definitions of the sort you are looking at right now. The particular case of the Resistances and Supports bot is a rather complex one, but does showcase the power of the tool!" + "text": "Again, visual scripting at its best! Plotters use stylized polygons made out of coordinate points to paint lines and shapes that represent data. Every layer made available on the charts is created with a set of definitions of the sort you are looking at right now. The particular case of the Resistances and Supports bot is a rather complex one, but does showcase the power of the tool!", + "translations": [ + { + "language": "IT", + "text": "Di nuovo, il meglio del visual scripting! I Plotters usano poligoni stilizzati definiti da punti e coordinate per disegnare linee e forme che rappresentano dati. Ogni layer disponibile sul grafico è creato da un insieme di definizioni come quello che stai guardando ora. Il caso del bot dei Supporti e Resistenze è abbastanza complesso, ma mostra la potenza di questo strumento!", + "updated": 1618057031198 + } + ] }, { "style": "Callout", "text": "Find the Resistance Zone 5 Polygon (to the left), expand it, and crawl your way up the branches for a sneak peek of how this beauty was built!", - "updated": 1610623154560 + "updated": 1610623154560, + "translations": [ + { + "language": "IT", + "text": "Cerca il Resistance 5 Polygon (qui a sinistra), espandilo e esplora i percorsi che collegano i vari componenti per osservare come è stata costruita questa bellezza!", + "updated": 1618057208787 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-060-tutorial-step-lets-do-some-testing.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-060-tutorial-step-lets-do-some-testing.json index 6d2199442..483e63bbc 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-060-tutorial-step-lets-do-some-testing.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-060-tutorial-step-lets-do-some-testing.json @@ -7,22 +7,50 @@ "project": "Superalgos", "name": "testing-trading-tasks" }, - "text": "We are back on the Network hierarchy to show you one of the core strategy-testing resources built-in the Trading Bot." + "text": "We are back on the Network hierarchy to show you one of the core strategy-testing resources built-in the Trading Bot.", + "translations": [ + { + "language": "IT", + "text": "Rieccoci nella gerarchia Network. Ora ti mostro una delle risorse chiave per testare le strategie di un Trading Bot.", + "updated": 1618057404730 + } + ] }, "paragraphs": [ { "style": "Text", "text": "But before you run your first Backtesting Session, let's go on a quick scouting mission to grasp how the Testing Trading Tasks node is set up.", - "updated": 1610638880718 + "updated": 1610638880718, + "translations": [ + { + "language": "IT", + "text": "Ma prima di lanciare la nostra prima Backtesting Session, lanciamoci in una piccola esplorazione per capire come è configurato il nodo delle Testing Trading Tasks.", + "updated": 1618057489202 + } + ] }, { "style": "Callout", "text": "Expand the Testing Trading Tasks node and look at the structure of offspring nodes... Looks familiar?", - "updated": 1616427797952 + "updated": 1616427797952, + "translations": [ + { + "language": "IT", + "text": "Espandi il nodo delle Testing Trading Tasks e guarda come è strutturato...ti ricorda qualcosa?", + "updated": 1618057585015 + } + ] }, { "style": "Text", - "text": "Indeed! It resembles the Data Tasks section: tasks are organized by exchange, market, and trading mine, so that you may test any number of strategies optimized for different markets, on multiple exchanges." + "text": "Indeed! It resembles the Data Tasks section: tasks are organized by exchange, market, and trading mine, so that you may test any number of strategies optimized for different markets, on multiple exchanges.", + "translations": [ + { + "language": "IT", + "text": "Esatto! Assomiglia alla sezione dei Data Tasks: le task sono organizzate per exchange, mercato e Trading Mine, cosicchè tu possa testare diverse strategie per mercati differenti e su exchange diversi.", + "updated": 1618057668667 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-061-tutorial-step-aim-high-trade-big.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-061-tutorial-step-aim-high-trade-big.json index 80f169f63..566acdbe1 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-061-tutorial-step-aim-high-trade-big.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-061-tutorial-step-aim-high-trade-big.json @@ -7,22 +7,50 @@ "project": "Superalgos", "name": "network-node" }, - "text": "Picture an army of bots working with multiple exchanges, markets, and strategies, running on a network ala trading farm." + "text": "Picture an army of bots working with multiple exchanges, markets, and strategies, running on a network ala trading farm.", + "translations": [ + { + "language": "IT", + "text": "Immagina un esercito di bots che lavorano con vari exchange, mercati e strategie, coordinati da un network che fa da trading farm.", + "updated": 1618057758985 + } + ] }, "paragraphs": [ { "style": "Text", "text": "That is what the Network Node is about. What you've seen so far is running on a single machine. But...", - "updated": 1616427867794 + "updated": 1616427867794, + "translations": [ + { + "language": "IT", + "text": "Il Network Node fa esattamente questo. I processi che hai visto finora girano su una singola macchina. Però...", + "updated": 1618057806513 + } + ] }, { "style": "Callout", "text": "Superalgos supports distributing and coordinating tasks across networks of nodes running the Client! This enables smart and scalable operations. Any machine running the GUI may control the enterprise!", - "updated": 1616693637435 + "updated": 1616693637435, + "translations": [ + { + "language": "IT", + "text": "Superalgos permette di distribuire e coordinare tasks attraverso una rete di macchine che eseguono il Client! Questo permette di eseguire operazioni avanzate e scalabili. Qualsiasi macchina che esegue la GUI può controllare il tutto!", + "updated": 1618057957707 + } + ] }, { "style": "Text", - "text": "You may set up a network with a few Raspberry Pi, an industrial-grade datacenter—or anything in between." + "text": "You may set up a network with a few Raspberry Pi, an industrial-grade datacenter—or anything in between.", + "translations": [ + { + "language": "IT", + "text": "Puoi creare network arbitrariamente complessi che vanno da qualche Raspberry Pi a un datacenter industriale.", + "updated": 1618058007870 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json index 8c96f8cbf..883f429c1 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json @@ -4,27 +4,55 @@ "type": "Tutorial Step - Machines Learn Too!", "definition": { "icon": { - "name": "tensorflow-project", - "project": "TensorFlow" + "name": "learning-tasks", + "project": "Superalgos" }, "text": "The latest version of Superalgos features an experimental integration of TensorFlow to leverage ML from within the app!", - "updated": 1616691534660 + "updated": 1616691534660, + "translations": [ + { + "language": "IT", + "text": "L'ultima versione di Superalgos presenta un integrazione sperimentale per sfruttare il machine learning.", + "updated": 1618058419040 + } + ] }, "paragraphs": [ { "style": "Text", "text": "The integration maps the definition of a NodeJS TensorFlow Library featuring a Supervised Learning algorithm and its Artificial Neural Network in the same kind of structure of nodes typical of Superalgos.", - "updated": 1616692845459 + "updated": 1616692845459, + "translations": [ + { + "language": "IT", + "text": "L'integrazione mappa la TensorFlow Library di NodeJS, che contiene un algoritmo di Supervised Learning e la relativa Artificial Neural Network, allo stesso tipo di struttura di nodi tipica di Superalgos.", + "updated": 1618058443954 + } + ] }, { "style": "Note", "text": "The integration leverages the rest of the Superalgos infrastructure, so that you may use your datasets to train ML algos and use the resulting models from within trading systems!", - "updated": 1616692959991 + "updated": 1616692959991, + "translations": [ + { + "language": "IT", + "text": "L'integrazione sfrutta l'infrastuttura di Superalgos, quindi puoi usare i tuoi datasets per fare il training degli algoritmi di ML e usarne i modelli direttamente dal Trading System.", + "updated": 1618058363973 + } + ] }, { "style": "Success", "text": "After doing the first few tutorials, take a look at the Machine Learning Demo Plugin Workspace!", - "updated": 1616693444144 + "updated": 1616693444144, + "translations": [ + { + "language": "IT", + "text": "Dopo i primi tutorial, dai un'occhiata a Machine Learning Demo Plugin Workspace!", + "updated": 1618058432041 + } + ] } ] } \ No newline at end of file From 9a8d14f34ee8058ba78e6de1ffd239e8136a0f9d Mon Sep 17 00:00:00 2001 From: 0xperez Date: Sat, 10 Apr 2021 19:16:20 +0200 Subject: [PATCH 21/32] Translating the Welcome Tutorial - Page 63 to 112 --- ...tutorial-step-beware-of-impersonators.json | 18 +++- ...s-063-tutorial-step-civil-works-ahead.json | 27 +++++- ...s-064-tutorial-step-enough-digressing.json | 27 +++++- ...algos-065-tutorial-step-what-when-how.json | 72 +++++++++++++-- ...lgos-066-tutorial-step-ready.-set.-go.json | 36 +++++++- ...tutorial-step-getting-to-the-fun-bits.json | 36 +++++++- ...torial-step-what-is-it-we-are-testing.json | 27 +++++- ...69-tutorial-step-green-silver-bullets.json | 36 +++++++- ...algos-070-tutorial-step-sell-it-quick.json | 36 +++++++- ...071-tutorial-step-shall-we-dig-deeper.json | 36 +++++++- ...-072-tutorial-step-whos-keeping-score.json | 18 +++- ...utorial-step-the-power-of-data-mining.json | 27 +++++- ...utorial-step-find-the-logic-challenge.json | 36 +++++++- ...075-tutorial-step-heres-how-it-works..json | 27 +++++- ...s-076-tutorial-step-come-meet-someone.json | 27 +++++- ...algos-077-tutorial-step-formulations..json | 36 +++++++- ...peralgos-078-tutorial-step-the-seller.json | 36 +++++++- ...-tutorial-step-simplifying-complexity.json | 36 +++++++- ...s-080-tutorial-step-lets-take-a-peek..json | 36 +++++++- ...tutorial-step-find-the-node-challenge.json | 27 +++++- ...superalgos-082-tutorial-step-found-it.json | 36 +++++++- ...s-083-tutorial-step-the-coolest-trick.json | 45 ++++++++-- ...sting-trading-engine-visualization-01.json | 9 +- ...lgos-085-tutorial-step-feedback-loops.json | 36 +++++++- ...sting-trading-engine-visualization-02.json | 9 +- ...os-087-tutorial-step-enough-chit-chat.json | 54 +++++++++-- ...peralgos-088-tutorial-step-disclaimer.json | 18 +++- ...torial-step-lets-start-with-100-bucks.json | 27 +++++- ...tutorial-step-check-your-spot-balance.json | 36 +++++++- ...-091-tutorial-step-enjoy-the-outdoors.json | 45 ++++++++-- ...92-tutorial-step-your-keys-your-coins.json | 36 +++++++- ...093-tutorial-step-fire-up-the-machine.json | 36 +++++++- ...os-094-tutorial-step-are-we-ready-yet.json | 36 +++++++- ...ralgos-095-tutorial-step-lets-do-this.json | 27 +++++- ...welcome-live-trading-process-progress.json | 9 +- ...-097-tutorial-step-check-your-console.json | 36 +++++++- ...ial-step-welcome-live-trading-console.json | 9 +- ...algos-099-tutorial-step-is-it-working.json | 27 +++++- ...p-welcome-live-trading-binance-orders.json | 9 +- ...-tutorial-step-monitoring-the-fun-way.json | 36 +++++++- ...peralgos-102-tutorial-step-whats-next.json | 27 +++++- ...3-tutorial-step-three-minutes-to-play.json | 36 +++++++- ...04-tutorial-step-what-else-is-cooking.json | 45 ++++++++-- ...orial-step-spread-the-word-on-twitter.json | 36 +++++++- ...ralgos-106-tutorial-step-back-to-work.json | 36 +++++++- ...7-tutorial-step-tabbed-search-results.json | 90 ++++++++++++++++--- ...08-tutorial-step-a-couple-more-things.json | 36 +++++++- ...109-tutorial-step-help-us-with-a-star.json | 36 +++++++- ...ralgos-110-tutorial-step-get-in-touch.json | 18 +++- ...utorial-step-ready-for-more-tutorials.json | 36 +++++++- ...-tutorial-step-my-only-friend-the-end.json | 36 +++++++- 51 files changed, 1480 insertions(+), 185 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-0.5-tutorial-step-beware-of-impersonators.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-0.5-tutorial-step-beware-of-impersonators.json index 69a938bbd..d66c6e294 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-0.5-tutorial-step-beware-of-impersonators.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-0.5-tutorial-step-beware-of-impersonators.json @@ -8,13 +8,27 @@ "name": "bullet-warning", "project": "Superalgos" }, - "updated": 1617608574624 + "updated": 1617608574624, + "translations": [ + { + "language": "IT", + "text": "Gli admin di Superalgos non ti contatteranno mai direttamente, a meno che non li contatti tu per primo.", + "updated": 1618074109290 + } + ] }, "paragraphs": [ { "style": "Warning", "text": "Scammers are lurking! Beware! It's no news that trading-related groups attract all sorts of scammers, and we are aware that they contact people in our groups attempting all sorts of tricks. We will never ask you for API keys, coins, or cash. In fact, we will never ask you to trust us in any way! We want to make it clear that if someone contacts you directly claiming to work with or for the project, it is a scam. Please report scammers in the Community group so that they may be banned, and to increase awareness of the problem, but also block them and report them to Telegram if the option is available.", - "updated": 1617608980211 + "updated": 1617608980211, + "translations": [ + { + "language": "IT", + "text": "Attenzione, gli scammers sono in agguato! Non è una novità che i gruppi riguardanti il trading attraggano ogni tipo di scammer, e siamo al corrente del fatto che contattino persone del gruppo tentando di truffarle. Non chiederemo mai API keys, crypto o soldi. Di fatto, non ti chiederemo di fidarti di noi in alcun modo! Vogliamo che sia chiaro che se qualcuno ti contatta direttamente e dichiarando di lavorare per o con il progetto, è uno scam. Per favore segnalate gli scammers nel canale Community così che possano essere bannati, bloccateli e se possibile segnalateli a Telegram stesso.", + "updated": 1618074329147 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-063-tutorial-step-civil-works-ahead.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-063-tutorial-step-civil-works-ahead.json index cb778a841..fc5464df0 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-063-tutorial-step-civil-works-ahead.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-063-tutorial-step-civil-works-ahead.json @@ -7,16 +7,37 @@ "project": "Superalgos", "name": "under-construction" }, - "text": "Please, do not be surprised to find an under construction sign here and there..." + "text": "Please, do not be surprised to find an under construction sign here and there...", + "translations": [ + { + "language": "IT", + "text": "Non sorprenderti se trovi segnali di \"lavori in corso\" qua e là...", + "updated": 1618059716381 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "As I mentioned earlier, Superalgos is constantly growing, and infrastructure architected for the upcoming version may occasionally be merged to the current version in a service pack, along with necessary fixes and minor improvements." + "text": "As I mentioned earlier, Superalgos is constantly growing, and infrastructure architected for the upcoming version may occasionally be merged to the current version in a service pack, along with necessary fixes and minor improvements.", + "translations": [ + { + "language": "IT", + "text": "Come detto prima, Superalgos è in continua evoluzione e gli sviluppi per la versione successiva potrebbero essere occasionalmente implementati nella versione corrente, per risolvere problemi o apportare piccole migliorie.", + "updated": 1618059772511 + } + ] }, { "style": "Callout", - "text": "If you are curious about what is cooking for the upcoming Superalgos release, join the Superalgos Develop Telegram group." + "text": "If you are curious about what is cooking for the upcoming Superalgos release, join the Superalgos Develop Telegram group.", + "translations": [ + { + "language": "IT", + "text": "Se vuoi scoprire cosa bolle in pentola per la prossima release di Superalgos, unisciti al canale Telegram Superalgos Develop.", + "updated": 1618059823365 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-064-tutorial-step-enough-digressing.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-064-tutorial-step-enough-digressing.json index 52a073552..80925a1ef 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-064-tutorial-step-enough-digressing.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-064-tutorial-step-enough-digressing.json @@ -7,17 +7,38 @@ "project": "Superalgos", "name": "backtesting-session" }, - "text": "We'll run a Backtesting Session with a bunch of preconfigured parameters so that you may have a quick glimpse at how simulations work." + "text": "We'll run a Backtesting Session with a bunch of preconfigured parameters so that you may have a quick glimpse at how simulations work.", + "translations": [ + { + "language": "IT", + "text": "Lanceremo una Backtesting Session con dei parametri preconfigurati così da dare un'occhiata al funzionamento delle simulazioni.", + "updated": 1618059892671 + } + ] }, "paragraphs": [ { "style": "Text", "text": "As you can see to the right, a trading session has a reference to a Trading System. That is, the Trading Bot will apply the rules of the referenced trading system to make decisions. There's also a reference to a Trading Engine, a subject worth its own chapter, so I'll leave it for later!", - "updated": 1610639102636 + "updated": 1610639102636, + "translations": [ + { + "language": "IT", + "text": "Come vedi a destra, una Trading Sessionsi riferisce a un Trading System. Ciò significa che il Trading Bot applicherà le regole del corrispondente Trading System per prendere decisioni. C'è anche un riferimento a un Trading Engine, ma di questo parleremo in un capitolo successivo.", + "updated": 1618059980494 + } + ] }, { "style": "Callout", - "text": "The trading session is affected by several parameters. Take a quick look at their configurations selecting Configure on the menu!" + "text": "The trading session is affected by several parameters. Take a quick look at their configurations selecting Configure on the menu!", + "translations": [ + { + "language": "IT", + "text": "La Trading Session è controllata da vari parametri. Dai un'occhiata alle loro configurazioni selezionando Configure dal menù!", + "updated": 1618060016221 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-065-tutorial-step-what-when-how.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-065-tutorial-step-what-when-how.json index 65ccb2762..be33b70fe 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-065-tutorial-step-what-when-how.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-065-tutorial-step-what-when-how.json @@ -7,38 +7,94 @@ "project": "Superalgos", "name": "trading-parameters" }, - "text": "Trading Parameters determine key aspects of how the trading session is run. Let's take a quick, superficial look..." + "text": "Trading Parameters determine key aspects of how the trading session is run. Let's take a quick, superficial look...", + "translations": [ + { + "language": "IT", + "text": "I Trading Parameters controllano gli aspetti chiave dell'esecuzione della sessione di trading. Diamo un'occhiata veloce...", + "updated": 1618060155151 + } + ] }, "paragraphs": [ { "style": "List", - "text": "Session Base Asset: no capital is assigned in BTC." + "text": "Session Base Asset: no capital is assigned in BTC.", + "translations": [ + { + "language": "IT", + "text": "Session Base Asset: 0 BTC", + "updated": 1618060455866 + } + ] }, { "style": "List", - "text": "Session Quoted Asset: 1000 USDT of initial capital." + "text": "Session Quoted Asset: 1000 USDT of initial capital.", + "translations": [ + { + "language": "IT", + "text": "Session Quoted Asset: 1000 USDT di capitale iniziale", + "updated": 1618060205541 + } + ] }, { "style": "List", - "text": "Time Range: we'll test a single day, 2020-09-01." + "text": "Time Range: we'll test a single day, 2020-09-01.", + "translations": [ + { + "language": "IT", + "text": "Time Range: test su un singolo giorno (2020-09-01)", + "updated": 1618060612074 + } + ] }, { "style": "List", - "text": "Time Frame: orders are placed/canceled every minute, thus 01-min is appropriate." + "text": "Time Frame: orders are placed/canceled every minute, thus 01-min is appropriate.", + "translations": [ + { + "language": "IT", + "text": "Time Frame: 01-min (dato che gli ordini vengono inseriti/cancellati ogni minuto)", + "updated": 1618060502887 + } + ] }, { "style": "List", "text": "Slippage: it's irrelevant for this case, as this particular trading system uses limit orders only.", - "updated": 1610639262905 + "updated": 1610639262905, + "translations": [ + { + "language": "IT", + "text": "Slippage: irrilevante in questo di Trading System", + "updated": 1618060520878 + } + ] }, { "style": "List", - "text": "Fee Structure: 0.1% is the lower Binance tier." + "text": "Fee Structure: 0.1% is the lower Binance tier.", + "translations": [ + { + "language": "IT", + "text": "Fee Structure: 0.1% è il livello iniziale di Binance.", + "updated": 1618060361331 + } + ] }, { "style": "Text", "text": "The remaining parameters do not affect the simulation. To learn more about Trading Parameters, take a look at the documentation.", - "updated": 1610640777415 + "updated": 1610640777415, + "translations": [ + { + "language": "IT", + "text": "I restanti parametri non influenzano questa simulazione. Se vuoi saperne di più, consulta la sezione Trading Parameters nella documentazione.", + "updated": 1618060588588 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-066-tutorial-step-ready.-set.-go.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-066-tutorial-step-ready.-set.-go.json index e28c72da4..25aa5cc0d 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-066-tutorial-step-ready.-set.-go.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-066-tutorial-step-ready.-set.-go.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "task" }, - "text": "Let's get going! This is going to be quick anyway, as we are testing a single day worth of historic data." + "text": "Let's get going! This is going to be quick anyway, as we are testing a single day worth of historic data.", + "translations": [ + { + "language": "IT", + "text": "Forza, iniziamo! Sarà comunque una cosa veloce, perchè stiamo testando dati di una sola giornata.", + "updated": 1618060660046 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "Running a trading task is quite similar to running a data mining task. The difference lies in that—after running the task—you also need to run the trading session." + "text": "Running a trading task is quite similar to running a data mining task. The difference lies in that—after running the task—you also need to run the trading session.", + "translations": [ + { + "language": "IT", + "text": "Eseguire una task di trading è simile a eseguire una task di data mining. La differenza sta nel fatto che, dopo aver lanciato la task, devi anche lanciare la trading session.", + "updated": 1618060706178 + } + ] }, { "style": "Callout", "text": "Select Run on the Task menu!

Now select Run on the Backtesting Session menu!", - "updated": 1616428472102 + "updated": 1616428472102, + "translations": [ + { + "language": "IT", + "text": "Seleziona Run dal menu Task, e poi seleziona Run dal menu della Backtesting Session!", + "updated": 1618060790679 + } + ] }, { "style": "Note", - "text": "When the progress notice of the Trading Process Instance get's to the 100% mark, stop the task and click Next." + "text": "When the progress notice of the Trading Process Instance get's to the 100% mark, stop the task and click Next.", + "translations": [ + { + "language": "IT", + "text": "Quando la progress bar della Trading Process Instance raggiunge il 100%, ferma la task e clicca Next.", + "updated": 1618060849542 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-067-tutorial-step-getting-to-the-fun-bits.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-067-tutorial-step-getting-to-the-fun-bits.json index de523cc76..fc986900a 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-067-tutorial-step-getting-to-the-fun-bits.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-067-tutorial-step-getting-to-the-fun-bits.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "time-machine" }, - "text": "I took the liberty of bringing you to a particular moment in time, interesting for what comes next." + "text": "I took the liberty of bringing you to a particular moment in time, interesting for what comes next.", + "translations": [ + { + "language": "IT", + "text": "Mi sono preso la libertà di portarti in un particolare momento del tempo, per mostrarti cosa succede.", + "updated": 1618060917160 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "You are about to be exposed to the beauty of simulations. Am I a simulation? Are you? Is this whole thing real?" + "text": "You are about to be exposed to the beauty of simulations. Am I a simulation? Are you? Is this whole thing real?", + "translations": [ + { + "language": "IT", + "text": "Stai per assistere alla bellezza delle simulazioni. Sono una simulazione? O lo sei tu? È reale tutto ciò?", + "updated": 1618060948467 + } + ] }, { "style": "Callout", - "text": "Look around and decide for yourself!" + "text": "Look around and decide for yourself!", + "translations": [ + { + "language": "IT", + "text": "Guardati intorno e decidilo tu!", + "updated": 1618060965103 + } + ] }, { "style": "Success", - "text": "First of all, notice you are now in the 1-minute time frame, thus, these are 1-minute candles. The span of time in your screen is little more than one hour, at the beginning of September 1st 2020." + "text": "First of all, notice you are now in the 1-minute time frame, thus, these are 1-minute candles. The span of time in your screen is little more than one hour, at the beginning of September 1st 2020.", + "translations": [ + { + "language": "IT", + "text": "Prima di tutto, nota che sei nel time frame 1-min, quindi queste sono candele da un minuto. L'intervallo di tempo sul tuo schermo è di circa un'ora, e si riferisce all'inizio del 1 settembre 2020.", + "updated": 1618061043559 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-068-tutorial-step-what-is-it-we-are-testing.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-068-tutorial-step-what-is-it-we-are-testing.json index 7b8bc42d8..935330c87 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-068-tutorial-step-what-is-it-we-are-testing.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-068-tutorial-step-what-is-it-we-are-testing.json @@ -7,13 +7,27 @@ "project": "Superalgos", "name": "trading-system" }, - "text": "We've run a backtest but we haven't discussed the Trading System we are testing! Let's go through the basics!" + "text": "We've run a backtest but we haven't discussed the Trading System we are testing! Let's go through the basics!", + "translations": [ + { + "language": "IT", + "text": "Abbiamo lanciato un backtest ma non abbiamo discusso del Trading System che stiamo testando! Facciamolo ora!", + "updated": 1618061084694 + } + ] }, "paragraphs": [ { "style": "Text", "text": "The trading idea is buy \"the falling knife\" and sell \"the rebound\". The strategy places a Limit Buy Order a distance below the price. If the order is not filled by the next minute, the order is canceled and a new order is placed, potentially at an adjusted rate. If the price drops suddenly, chances are the order will get filled. If that happens, then the strategy tries to sell at a higher price.", - "updated": 1616428600039 + "updated": 1616428600039, + "translations": [ + { + "language": "IT", + "text": "L'idea è comprare il \"falling knife\" e vendere il \"rebound\". La strategia piazza un Limit Buy Order al di sotto dell'attuale prezzo. Se l'ordine non viene evaso nel giro del minuto successivo, viene cancellato e ne viene creato uno nuovo, eventualmente a un prezzo migliore. Se il prezzo scende, è probabile che l'ordine venga evaso: a quel punto la strategia tenta di vendere a un prezzo maggiore.", + "updated": 1618061264322 + } + ] }, { "style": "Text", @@ -22,7 +36,14 @@ { "style": "Note", "text": "Let's not discuss the merits of the trading idea but the implementation. This is just a demo to show off the capacities of the Trading Bot, not the strategy per se.", - "updated": 1610640921014 + "updated": 1610640921014, + "translations": [ + { + "language": "IT", + "text": "Non discutiamo dell'efficacia del metodo, ma della sua implementazione. Questa è una demo per mostrare le capacità del Trading Bot, non la strategia in sè.", + "updated": 1618061327170 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-069-tutorial-step-green-silver-bullets.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-069-tutorial-step-green-silver-bullets.json index 324027cc1..10dd29338 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-069-tutorial-step-green-silver-bullets.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-069-tutorial-step-green-silver-bullets.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "bullet-limit-buy-order" }, - "text": "Do you see the green bullets with an L in the center? Those are the limit buy orders I mentioned." + "text": "Do you see the green bullets with an L in the center? Those are the limit buy orders I mentioned.", + "translations": [ + { + "language": "IT", + "text": "Vedi quei cerchi verdi con dentro la \"L\"? Sono i Limit Buy Order di cui parlavo.", + "updated": 1618061409837 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "Notice how an order is placed every minute and is canceled before a new order is placed. Do you recognize the symbol for the order cancellation? It's the smaller, darker bullet with a white horizontal stripe in the middle!" + "text": "Notice how an order is placed every minute and is canceled before a new order is placed. Do you recognize the symbol for the order cancellation? It's the smaller, darker bullet with a white horizontal stripe in the middle!", + "translations": [ + { + "language": "IT", + "text": "Nota come viene inserito un ordine al minuto, e come questo viene cancellato prima di inserirne uno nuovo: quest'ultimo evento è riconoscibile dal cerchio scuro più piccolo con una striscia orizziontale che lo attraversa!", + "updated": 1618061508009 + } + ] }, { "style": "Callout", - "text": "Notice the knife falling at 00:21 AM! The price fell well below the rate of the limit order, therefore, the order was filled! That is what the bigger—filled—green bullet indicates!" + "text": "Notice the knife falling at 00:21 AM! The price fell well below the rate of the limit order, therefore, the order was filled! That is what the bigger—filled—green bullet indicates!", + "translations": [ + { + "language": "IT", + "text": "Nota il \"falling knife\" delle 00:21! Il prezzo scende al di sotto di quello del limit order, che quindi viene evaso. Ciò è indicato dal cerchio più grande riempito di colore verde!", + "updated": 1618061604262 + } + ] }, { "style": "Text", "text": "So. . . what happens afterwards?", - "updated": 1610536393495 + "updated": 1610536393495, + "translations": [ + { + "language": "IT", + "text": "Quindi...dopo che succede?", + "updated": 1618061624143 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-070-tutorial-step-sell-it-quick.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-070-tutorial-step-sell-it-quick.json index 05c4806ef..61cd402c7 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-070-tutorial-step-sell-it-quick.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-070-tutorial-step-sell-it-quick.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "bullet-limit-sell-order" }, - "text": "I'm sure you noted there are no more limit buy orders after the order got filled. Instead, sell orders start popping up!" + "text": "I'm sure you noted there are no more limit buy orders after the order got filled. Instead, sell orders start popping up!", + "translations": [ + { + "language": "IT", + "text": "Sicuramente hai notato che non ci sono più limit buy orders: al loro posto, cominciano ad apparire i sell orders!", + "updated": 1618061675585 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Notice how the first Limit Sell Order is placed at 00:22 AM, the minute after the buy order filled!" + "text": "Notice how the first Limit Sell Order is placed at 00:22 AM, the minute after the buy order filled!", + "translations": [ + { + "language": "IT", + "text": "Nota come il Limit Sell Order è inserito alle 00:22, un minuto dopo che il buy order è stato evaso.", + "updated": 1618061709740 + } + ] }, { "style": "Text", "text": "It's the same minute Superalgos would have gotten notice from the exchange that the order got filled. The Trading Bot connects with the exchange and goes through two distinct cycles. ", - "updated": 1616428810807 + "updated": 1616428810807, + "translations": [ + { + "language": "IT", + "text": "È lo stesso minuto in cui Superalgos viene notificato dall'exchange che l'ordine è stato evaso. Il Trading Bot si connette con l'exchange e esegue due cicli distinti di operazioni.", + "updated": 1618061767833 + } + ] }, { "style": "Success", - "text": "In the first Cycle, it finds out the status of existing orders. In the second, it gives new instructions." + "text": "In the first Cycle, it finds out the status of existing orders. In the second, it gives new instructions.", + "translations": [ + { + "language": "IT", + "text": "Nel primo Cycle, controlla lo stato degli ordini esistenti. Nel secondo, dà nuove istruzioni.", + "updated": 1618061798692 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-071-tutorial-step-shall-we-dig-deeper.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-071-tutorial-step-shall-we-dig-deeper.json index cdc24e6cb..8a6196125 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-071-tutorial-step-shall-we-dig-deeper.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-071-tutorial-step-shall-we-dig-deeper.json @@ -8,20 +8,48 @@ "name": "layer-resistance" }, "text": "The logic behind the placing of buy orders is influenced by the Resistances and Supports indicator bot from the Masters Data Mine you ran earlier.", - "updated": 1610641051577 + "updated": 1610641051577, + "translations": [ + { + "language": "IT", + "text": "L'inserimento dei buy orders è influenzato dai supporti e resistenze dell'Indicator Bot della Masters Data Mine che abbiamo eseguito prima.", + "updated": 1618061894381 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "I took the liberty to turn the Supports layer on to show you this beauty... I hope you don't mind!" + "text": "I took the liberty to turn the Supports layer on to show you this beauty... I hope you don't mind!", + "translations": [ + { + "language": "IT", + "text": "Mi sono preso la libertà di attivare il layer dei Supporti per mostrarti questa bellezza. Spero non ti dispiaccia!", + "updated": 1618061926335 + } + ] }, { "style": "Callout", - "text": "The indicator identifies levels (price ranges) on which price is rejected, and keeps a counter of how many rejections occur until the level is breached." + "text": "The indicator identifies levels (price ranges) on which price is rejected, and keeps a counter of how many rejections occur until the level is breached.", + "translations": [ + { + "language": "IT", + "text": "L'indicatore identifica livelli (range di prezzo) oltre i quali il prezzo fatica a salire, e tiene conto di quante volte è respinto da essi prima di romperli.", + "updated": 1618062124164 + } + ] }, { "style": "Text", - "text": "The way levels are represented on-screen varies with the number of rejections the level has witnessed, giving us a visual clue of how strong each support level may be. Once a level is breached, it disappears." + "text": "The way levels are represented on-screen varies with the number of rejections the level has witnessed, giving us a visual clue of how strong each support level may be. Once a level is breached, it disappears.", + "translations": [ + { + "language": "IT", + "text": "Il modo in cui i livelli sono disegnati varia a seconda del numero di \"rimbalzi\" del prezzo su quel livello, dandoci un'idea visiva di quanto sia forte il supporto. Una volta che viene rotto, sparisce.", + "updated": 1618062095822 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-072-tutorial-step-whos-keeping-score.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-072-tutorial-step-whos-keeping-score.json index 4a1cecd39..2d3e99107 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-072-tutorial-step-whos-keeping-score.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-072-tutorial-step-whos-keeping-score.json @@ -7,7 +7,14 @@ "project": "Superalgos", "name": "layer-resistance" }, - "text": "Check the table below and see if you can interpret the support levels you see on the charts." + "text": "Check the table below and see if you can interpret the support levels you see on the charts.", + "translations": [ + { + "language": "IT", + "text": "Guarda questa tabella per interpretare i livelli di supporto che vedi sul grafico.", + "updated": 1618062212883 + } + ] }, "paragraphs": [ { @@ -16,7 +23,14 @@ }, { "style": "Text", - "text": "
For a new support level with one rejection, the dotted line marks the exact level on which price bounced. For further rejections, the blocks mark the rate ranges on which subsequent rejections are counted." + "text": "
For a new support level with one rejection, the dotted line marks the exact level on which price bounced. For further rejections, the blocks mark the rate ranges on which subsequent rejections are counted.", + "translations": [ + { + "language": "IT", + "text": "
Per un nuovo livello di supporto appena creato, la linea tratteggita segna esattamente dove il prezzo ha rimbalzato. Per ogni rimbalzo futuro, il blocco cambia colore.", + "updated": 1618062387108 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-073-tutorial-step-the-power-of-data-mining.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-073-tutorial-step-the-power-of-data-mining.json index cf1898d4c..d99637e34 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-073-tutorial-step-the-power-of-data-mining.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-073-tutorial-step-the-power-of-data-mining.json @@ -7,17 +7,38 @@ "project": "Superalgos", "name": "layer-resistance" }, - "text": "Why do levels jump up and down? There's something I haven't told you yet, 'cos I'm afraid it may blow your mind!" + "text": "Why do levels jump up and down? There's something I haven't told you yet, 'cos I'm afraid it may blow your mind!", + "translations": [ + { + "language": "IT", + "text": "Perchè i livelli saltano su e giù? C'è qualcosa che ancora non ti ho detto, e vedrai che ti farà impazzire!", + "updated": 1618064409000 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "The bot keeps track of all support levels alive since the start of the dataset, but only shows you the five levels closest to the current price." + "text": "The bot keeps track of all support levels alive since the start of the dataset, but only shows you the five levels closest to the current price.", + "translations": [ + { + "language": "IT", + "text": "Il bot tiene traccia di tutti i livelli di supporto esistenti dall'inizio del dataset, ma ti mostra solo i cinque livelli più vicini al prezzo corrente.", + "updated": 1618062479544 + } + ] }, { "style": "Text", "text": "Keeping track of information for the whole span of the dataset—which may count years—is the extraordinary value of data mining, and the kind of things you wouldn't be able to calculate with a function, on the fly. The Plotter associated with the Indicator Bot dynamically shows the five levels of support closest to the price because those are the relevant levels for the context, and it's how the plotter is built!", - "updated": 1616429006453 + "updated": 1616429006453, + "translations": [ + { + "language": "IT", + "text": "Tenere traccia dei dati per tutto il periodo temporale definito dal dataset (che può essere di anni) è il grande potere del data mining, e il tipo di informazioni che non puoi ricavare facilmente. Il Plotter associato all'Indicator Bot mostra dinamicamente i cinque livelli più vicini al prezzo attuale perchè sono i più rilevanti, ed è così che il Plotter è stato configurato!", + "updated": 1618064485684 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-074-tutorial-step-find-the-logic-challenge.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-074-tutorial-step-find-the-logic-challenge.json index 885eed643..b496f59bd 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-074-tutorial-step-find-the-logic-challenge.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-074-tutorial-step-find-the-logic-challenge.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "layer-resistance" }, - "text": "Now that you know how the indicator works, can you find the relationship between buy orders and support levels?" + "text": "Now that you know how the indicator works, can you find the relationship between buy orders and support levels?", + "translations": [ + { + "language": "IT", + "text": "Ora che sai come funzionano gli indicatori, puoi trovare la relazione tra buy orders e livelli di supporto?", + "updated": 1618064528654 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Take some time to explore the period of time tested looking for clues on how support levels determine the rate of the Limit Buy Order!" + "text": "Take some time to explore the period of time tested looking for clues on how support levels determine the rate of the Limit Buy Order!", + "translations": [ + { + "language": "IT", + "text": "Prenditi un'attimo per esplorare il periodo di tempo testato e cercare indizi su come i livelli di supporto determinino l'inserimento del Limit Buy Order!", + "updated": 1618064580106 + } + ] }, { "style": "Text", - "text": "It's fun noticing how new levels form when price changes direction, and how an established level changes color when price bounces-off it." + "text": "It's fun noticing how new levels form when price changes direction, and how an established level changes color when price bounces-off it.", + "translations": [ + { + "language": "IT", + "text": "È divertente osservare come i nuovi livelli si formano quando il prezzo cambia direzione, e come un livello cambia colore quando respinge il prezzo.", + "updated": 1618064645034 + } + ] }, { "style": "Success", - "text": "But the trick lies in counting levels above the order!" + "text": "But the trick lies in counting levels above the order!", + "translations": [ + { + "language": "IT", + "text": "Il trucco sta nel contare i livelli sopra l'ordine!", + "updated": 1618064660104 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-075-tutorial-step-heres-how-it-works..json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-075-tutorial-step-heres-how-it-works..json index 48aaa3e6b..e8930974c 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-075-tutorial-step-heres-how-it-works..json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-075-tutorial-step-heres-how-it-works..json @@ -7,16 +7,37 @@ "project": "Superalgos", "name": "layer-resistance" }, - "text": "Got it? The Trading Bot places the Limit Buy Order at the fourth support level! What's the logic behind this?" + "text": "Got it? The Trading Bot places the Limit Buy Order at the fourth support level! What's the logic behind this?", + "translations": [ + { + "language": "IT", + "text": "Hai capito? Il Trading Bot piazza i Limit Buy Order al quarto livello di supporto! Qual'è la logica di questa scelta?", + "updated": 1618064697343 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "It's sort of arbitrary, but the strategy defines a falling knife as the price action capable of breaching at least three support levels and getting to the fourth during a single minute. Statistically, such events—in this time frame—produce more bounces than continuations. They may be caused by large market orders that temporarily increase the bid/ask spread in the order book." + "text": "It's sort of arbitrary, but the strategy defines a falling knife as the price action capable of breaching at least three support levels and getting to the fourth during a single minute. Statistically, such events—in this time frame—produce more bounces than continuations. They may be caused by large market orders that temporarily increase the bid/ask spread in the order book.", + "translations": [ + { + "language": "IT", + "text": "È una scelta più o meno arbitraria, ma la strategia definisce come \"falling knife\" la price action che riesce a rompere almeno tre livelli di supporto e raggiungere il quarto nel giro di un singolo minuto. Statisticamente, questi eventi (su questo time frame) producono più rimbalzi che proseguimenti. Possono essere causati da market orders di grandi dimensioni che aumentano temporaneamente il bid/ask spread nell'order book.", + "updated": 1618064825884 + } + ] }, { "style": "Callout", - "text": "Take a minute to verify that buy orders are placed at the fifth support level!" + "text": "Take a minute to verify that buy orders are placed at the fifth support level!", + "translations": [ + { + "language": "IT", + "text": "Prenditi un attimo per verificare che i buy orders siano effettivamente piazzati al quinto supporto!", + "updated": 1618064944102 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-076-tutorial-step-come-meet-someone.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-076-tutorial-step-come-meet-someone.json index 2c7f10f2e..7dca4de62 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-076-tutorial-step-come-meet-someone.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-076-tutorial-step-come-meet-someone.json @@ -7,16 +7,37 @@ "project": "Superalgos", "name": "execution-algorithm" }, - "text": "Sorry for dragging you away from the charts, but I wanted to introduce you to someone: the guy on the right is the one placing the buy orders!" + "text": "Sorry for dragging you away from the charts, but I wanted to introduce you to someone: the guy on the right is the one placing the buy orders!", + "translations": [ + { + "language": "IT", + "text": "Scusa se ti ho trascinato via dai grafici, ma volevo presentarti a qualcuno: il tipo qui a destra è quello che piazza tutti i buy order!", + "updated": 1618064981900 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "We are inside the Lightning Strike Trading System, within the definitions of the Open Stage. In this stage, the Execution Algorithm takes over after the decision to take a position has already been made on the Trigger Stage. I know you still don't know what a Situation or a Condition are, but I'd still like you to do something..." + "text": "We are inside the Lightning Strike Trading System, within the definitions of the Open Stage. In this stage, the Execution Algorithm takes over after the decision to take a position has already been made on the Trigger Stage. I know you still don't know what a Situation or a Condition are, but I'd still like you to do something...", + "translations": [ + { + "language": "IT", + "text": "Siamo all'interno del Lightning Strike Trading System, dentro la definizione dell'Open Stage. In questo stage, l'Execution Algorithm prende il sopravvento dopo che la decisione di aprire una posizione è già stata presa nel Trigger Stage. So che non sai ancora cosa siano una Situation o una Condition, ma vorrei comunque facessi una cosa...", + "updated": 1618065153377 + } + ] }, { "style": "Callout", - "text": "Take a few minutes to explore the nodes below the execution algorithm, check the formulas and conditions, and see what you can make of them!" + "text": "Take a few minutes to explore the nodes below the execution algorithm, check the formulas and conditions, and see what you can make of them!", + "translations": [ + { + "language": "IT", + "text": "Esplora i nodi sotto l'Execution Algorithm, controlla le formule e condizioni, e vedi cosa puoi ricavarne!", + "updated": 1618065182365 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-077-tutorial-step-formulations..json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-077-tutorial-step-formulations..json index 218f65ec0..ec52f11b4 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-077-tutorial-step-formulations..json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-077-tutorial-step-formulations..json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "formula" }, - "text": "What you just went through is the definition of the Limit Buy Order that is placed and cancelled every minute until it gets filled." + "text": "What you just went through is the definition of the Limit Buy Order that is placed and cancelled every minute until it gets filled.", + "translations": [ + { + "language": "IT", + "text": "Quella che hai appena guardato è la definizione del Limit Buy Order che viene piazzato e cancellato ogni minuto finchè non viene evaso.", + "updated": 1618065276195 + } + ] }, "paragraphs": [ { "style": "Text", "text": "This is the node that determines the rate of the limit order. Remember what we discussed earlier about placing the order at the rate of the fourth support level?", - "updated": 1616429339703 + "updated": 1616429339703, + "translations": [ + { + "language": "IT", + "text": "Questo è il nodo che determina il prezzo del limit order. Ricordi quando abbiamo parlato di come l'ordine viene piazzato al quarto livello di supporto?", + "updated": 1618065331055 + } + ] }, { "style": "Callout", - "text": "Go to the Formula attached to the Order Rate node and click Edit on the menu." + "text": "Go to the Formula attached to the Order Rate node and click Edit on the menu.", + "translations": [ + { + "language": "IT", + "text": "Vai alla Formula collegata al nodo Order Rate e clicca Edit sul menu.", + "updated": 1618065364382 + } + ] }, { "style": "Text", - "text": "Well... that is how it's done! As you can see, the syntax is virtually self-explanatory! It involves defining the time frame, the indicator, and the indicator property involved." + "text": "Well... that is how it's done! As you can see, the syntax is virtually self-explanatory! It involves defining the time frame, the indicator, and the indicator property involved.", + "translations": [ + { + "language": "IT", + "text": "Ecco, è così che funziona! Come vedi, la sintassi è intuitiva. Comprende la definizione del time frame, degli indicatori interessati e delle loro proprietà.", + "updated": 1618065469493 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-078-tutorial-step-the-seller.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-078-tutorial-step-the-seller.json index 1e094f7cf..c087bbbbc 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-078-tutorial-step-the-seller.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-078-tutorial-step-the-seller.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "execution-algorithm" }, - "text": "We are now in the Close Stage. I thought it would be interesting to tell you more about execution algorithms, with another example." + "text": "We are now in the Close Stage. I thought it would be interesting to tell you more about execution algorithms, with another example.", + "translations": [ + { + "language": "IT", + "text": "Ora siamo nel Close Stage. Pensavo sarebbe stato interessante dirti di più sugli Execution Algorithm con un altro esempio.", + "updated": 1618065500220 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "An Execution Algorithm may handle multiple orders, of all types. In this case, multiple limit sell orders are defined." + "text": "An Execution Algorithm may handle multiple orders, of all types. In this case, multiple limit sell orders are defined.", + "translations": [ + { + "language": "IT", + "text": "Un Execution Algorithm può gestire più ordini di ogni tipo. In questo caso, vari limit sell orders sono definiti.", + "updated": 1618065545085 + } + ] }, { "style": "Callout", - "text": "Select Configure on the menu of the algorithm and reflect on the implications of this definition!" + "text": "Select Configure on the menu of the algorithm and reflect on the implications of this definition!", + "translations": [ + { + "language": "IT", + "text": "Seleziona Configure dal menu dell'algoritmo e rifletti sulle implicazioni di questa definizione!", + "updated": 1618065569642 + } + ] }, { "style": "Text", - "text": "Both the open stage, where you define how to take a position, and the close stage, where you define how to exit, may feature multiple execution algorithms, each of them handling a certain amount of capital." + "text": "Both the open stage, where you define how to take a position, and the close stage, where you define how to exit, may feature multiple execution algorithms, each of them handling a certain amount of capital.", + "translations": [ + { + "language": "IT", + "text": "Sia l'Open Stage, dove definisci come aprire una posizione, che il Close Stage, dove invece definisci come chiuderla, possono contenere diversi Execution Algorithm, ognuno dei quali gestisce un certo capitale.", + "updated": 1618065707647 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-079-tutorial-step-simplifying-complexity.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-079-tutorial-step-simplifying-complexity.json index ba23c42ed..0428512f0 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-079-tutorial-step-simplifying-complexity.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-079-tutorial-step-simplifying-complexity.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "trading-system" }, - "text": "We haven't discussed trading systems as a framework, but a feature relevant to this explanation is that they may handle multiple strategies." + "text": "We haven't discussed trading systems as a framework, but a feature relevant to this explanation is that they may handle multiple strategies.", + "translations": [ + { + "language": "IT", + "text": "Non abbiamo discusso dei Trading System come dei framework, ma un feature di rilievo in questo senso è che possono gestire diverse strategie.", + "updated": 1618065765945 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "Each strategy features an Open Stage and a Close Stage, each with its own execution definitions. Each stage may feature multiple execution algorithms, and each algorithm may handle multiple orders." + "text": "Each strategy features an Open Stage and a Close Stage, each with its own execution definitions. Each stage may feature multiple execution algorithms, and each algorithm may handle multiple orders.", + "translations": [ + { + "language": "IT", + "text": "Ogni strategia ha un Open Stage e un Close Stage, ognuno dei quali ha i propri metodi di esecuzione. Ogni stage può avere diversi execution algorithms e ognuno di questi può gestire vari ordini.", + "updated": 1618065861963 + } + ] }, { "style": "Callout", - "text": "Do you see the pattern? We call it granularity." + "text": "Do you see the pattern? We call it granularity.", + "translations": [ + { + "language": "IT", + "text": "Riesci a vedere lo schema? Noi lo chiamiamo granularità.", + "updated": 1618065885044 + } + ] }, { "style": "Text", - "text": "Superalgos breaks down each issue to the minimum expression, and integrates the solutions. This is how it allows you to design, deploy, and manage both simple and the most complex trading setups you may envision." + "text": "Superalgos breaks down each issue to the minimum expression, and integrates the solutions. This is how it allows you to design, deploy, and manage both simple and the most complex trading setups you may envision.", + "translations": [ + { + "language": "IT", + "text": "Superalgos decompone ogni problema al minimo, e integra le soluzioni. In questo modo ti permette di progettare, rilasciare e gestire ogni tipo di trading setup, semplice o complesso, che vuoi implementare!", + "updated": 1618065967425 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-080-tutorial-step-lets-take-a-peek..json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-080-tutorial-step-lets-take-a-peek..json index f4bea1508..15e27a1b0 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-080-tutorial-step-lets-take-a-peek..json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-080-tutorial-step-lets-take-a-peek..json @@ -7,17 +7,38 @@ "project": "Superalgos", "name": "limit-sell-order" }, - "text": "Before we leave the trading system, let's take a quick look into one of these orders and see what may be of interest." + "text": "Before we leave the trading system, let's take a quick look into one of these orders and see what may be of interest.", + "translations": [ + { + "language": "IT", + "text": "Prima di abbandonare il trading system, diamo un'occhiata veloce a uno di questi ordini e vediamo cosa c'è di interessante.", + "updated": 1618066037707 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Expand Profit 0.6 and check the formula of the Order Rate node." + "text": "Expand Profit 0.6 and check the formula of the Order Rate node.", + "translations": [ + { + "language": "IT", + "text": "Espandi Profit 0.6 e osserva la formula nel nodo Order Rate.", + "updated": 1618066067329 + } + ] }, { "style": "Text", "text": "Let's focus on this misterious bit of the formula:", - "updated": 1610642070428 + "updated": 1610642070428, + "translations": [ + { + "language": "IT", + "text": "Analizziamo questa parte misteriosa:
", + "updated": 1618067107241 + } + ] }, { "style": "Text", @@ -35,7 +56,14 @@ }, { "style": "Text", - "text": "The formula is fetching the value of the Exit Target Rate, defined elsewhere. Let's not focus on what this target rate may be. Instead, let's take a look at the mechanism by which a Trading System may have access to information processed by the Trading Bot." + "text": "The formula is fetching the value of the Exit Target Rate, defined elsewhere. Let's not focus on what this target rate may be. Instead, let's take a look at the mechanism by which a Trading System may have access to information processed by the Trading Bot.", + "translations": [ + { + "language": "IT", + "text": "La formula recupera il valore dell'Exit Target Rate, definito altrove. Non soffermiamoci su cosa sia questo target rate: piuttosto, diamo un'occhiata al meccanismo con il quale il Trading System ha acceso alle informazioni processate dal Trading Bot.", + "updated": 1618067231613 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-081-tutorial-step-find-the-node-challenge.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-081-tutorial-step-find-the-node-challenge.json index 0919ede45..72fddfef3 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-081-tutorial-step-find-the-node-challenge.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-081-tutorial-step-find-the-node-challenge.json @@ -7,13 +7,27 @@ "project": "Superalgos", "name": "trading-engine" }, - "text": "The Trading Engine administers the complexity entailed in automated trading by making information accessible to users and trading systems." + "text": "The Trading Engine administers the complexity entailed in automated trading by making information accessible to users and trading systems.", + "translations": [ + { + "language": "IT", + "text": "Il Trading Engine gestisce la complessità del trading automatico rendendo le informazioni accessibili agli utenti e ai sistemi di trading.", + "updated": 1618067277865 + } + ] }, "paragraphs": [ { "style": "Text", "text": "Rember my comments about granularity? Remember how the formula on the trading system fetched the value of the exit target rate? Here's a quick reminder:", - "updated": 1610536534720 + "updated": 1610536534720, + "translations": [ + { + "language": "IT", + "text": "Ricordi i miei commenti sulla granularità? Ricordi come la formula del trading system prendeva il valore dell'Exit Target Rate? Ecco un promemoria:", + "updated": 1618067378217 + } + ] }, { "style": "Json", @@ -22,7 +36,14 @@ { "style": "Callout", "text": "This string holds the path to that piece of information in the data structure of the Trading Engine hierarchy! Can you find the Exit Target Rate node? Expand the hierarchy and follow the breadcrumb trail!", - "updated": 1616429836465 + "updated": 1616429836465, + "translations": [ + { + "language": "IT", + "text": "Questa stringa contiene il percorso a quel dato nel contesto della struttura della gerarchia del Trading Engine! Riesci a trovare il nodo dell'Exit Target Rate? Espandi la gerarchia e seguila!", + "updated": 1618067490282 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-082-tutorial-step-found-it.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-082-tutorial-step-found-it.json index 7a197a6cc..363ca413b 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-082-tutorial-step-found-it.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-082-tutorial-step-found-it.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "copy-path" }, - "text": "This is how the Trading Engine makes every bit of information processed by the Trading Bot available to trading systems." + "text": "This is how the Trading Engine makes every bit of information processed by the Trading Bot available to trading systems.", + "translations": [ + { + "language": "IT", + "text": "È in questo modo che il Trading Engine rende ogni dato processato dal Trading Bot disponibile a tutti i trading system.", + "updated": 1618067637676 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "There is a path to every piece of data, and by knowing the path, you may access the data from within any Formula or Condition in a Trading Strategy. Let's run a quick check:" + "text": "There is a path to every piece of data, and by knowing the path, you may access the data from within any Formula or Condition in a Trading Strategy. Let's run a quick check:", + "translations": [ + { + "language": "IT", + "text": "Esiste un percorso a ogni informazione, e conoscendolo è possibile accedervi da ogni Formula o Condition di una Trading Strategy. Facciamo una prova:", + "updated": 1618067702996 + } + ] }, { "style": "Callout", - "text": "Open the menu of the Exit Target Rate node to the left, and click Copy Node Path. Now, open a text editor and paste what you copied." + "text": "Open the menu of the Exit Target Rate node to the left, and click Copy Node Path. Now, open a text editor and paste what you copied.", + "translations": [ + { + "language": "IT", + "text": "Apri il menu del nodo Exit Target Rate a sinistra, e clicca Copy Node Path. Poi apri un editor di testo e incolla ciò che hai copiato.", + "updated": 1618067741606 + } + ] }, { "style": "Text", - "text": "Ok! This is how formulas and conditions access the information... How about humans?" + "text": "Ok! This is how formulas and conditions access the information... How about humans?", + "translations": [ + { + "language": "IT", + "text": "Okay, quindi formule e condizioni accedono ai dati in questo modo. E invece gli umani?", + "updated": 1618067770485 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-083-tutorial-step-the-coolest-trick.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-083-tutorial-step-the-coolest-trick.json index 9de6305ee..c68e6bfb3 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-083-tutorial-step-the-coolest-trick.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-083-tutorial-step-the-coolest-trick.json @@ -7,25 +7,60 @@ "project": "Superalgos", "name": "exit-target-rate" }, - "text": "Humans may access this information by using a cool trick that makes the charting space interact with the design space!" + "text": "Humans may access this information by using a cool trick that makes the charting space interact with the design space!", + "translations": [ + { + "language": "IT", + "text": "Gli umani possono accedere a questi dati utilizzando un trucchetto che permette al Charting Space di interagire con il Design Space.", + "updated": 1618067821598 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "To use this trick, I just did the following:" + "text": "To use this trick, I just did the following:", + "translations": [ + { + "language": "IT", + "text": "Per usare questo trucco basta fare così:", + "updated": 1618067975774 + } + ] }, { "style": "List", - "text": "Split the screen in half pulling the slider up so that we can see both spaces at the same time." + "text": "Split the screen in half pulling the slider up so that we can see both spaces at the same time.", + "translations": [ + { + "language": "IT", + "text": "Dividi lo schermo in due trascinando lo slider in su, così che possiamo vedere entrambi gli spazi", + "updated": 1618067893855 + } + ] }, { "style": "List", "text": "Turn on the Current Position layer on the Trading engine layer manager. I chose this layer because it corresponds to this section of the hierarchy... tradingEngine.tradingCurrent.position, remember?", - "updated": 1616430381277 + "updated": 1616430381277, + "translations": [ + { + "language": "IT", + "text": "Attiva il layer Current Position nel layer manager del Trading Engine. Ho scelto questo layer perchè corrisponde alla famosa sezione della gerarchia... tradingEngine.tradingCurrent.position, ricordi?", + "updated": 1618067950391 + } + ] }, { "style": "Callout", - "text": "Now, slide the mouse pointer across the candles on which the position is taken and see what happens on the nodes to the left..." + "text": "Now, slide the mouse pointer across the candles on which the position is taken and see what happens on the nodes to the left...", + "translations": [ + { + "language": "IT", + "text": "Ora, trascina il puntatore del mouse attraverso le candele sulle quali è definita la posizione e guarda cosa succede ai nodi a sinistra...", + "updated": 1618068017032 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-084-tutorial-step-welcome-backtesting-trading-engine-visualization-01.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-084-tutorial-step-welcome-backtesting-trading-engine-visualization-01.json index b708de744..63747490e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-084-tutorial-step-welcome-backtesting-trading-engine-visualization-01.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-084-tutorial-step-welcome-backtesting-trading-engine-visualization-01.json @@ -3,7 +3,14 @@ "pageNumber": 84, "type": "Tutorial Step - Welcome Backtesting Trading Engine Visualization 01", "definition": { - "text": "This step will play a video in full screen mode." + "text": "This step will play a video in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo step eseguirà un video a schermo intero.", + "updated": 1618068032985 + } + ] }, "paragraphs": [ { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-085-tutorial-step-feedback-loops.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-085-tutorial-step-feedback-loops.json index 3c00ae0a6..28137a0c0 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-085-tutorial-step-feedback-loops.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-085-tutorial-step-feedback-loops.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "limit-buy-order" }, - "text": "Lets take a look at another example to let the notion of the constant feedback loop sink in before we move on!" + "text": "Lets take a look at another example to let the notion of the constant feedback loop sink in before we move on!", + "translations": [ + { + "language": "IT", + "text": "Diamo un'occhiata a un altro esempio per assorbire bene la nozione di \"constant feedback loop\" prima di proseguire!", + "updated": 1618068120939 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "This is the data structure where information about limit buy orders is kept." + "text": "This is the data structure where information about limit buy orders is kept.", + "translations": [ + { + "language": "IT", + "text": "Questa è la struttura di dati dove si trovano le informazioni sui limit buy orders.", + "updated": 1618068157301 + } + ] }, { "style": "Callout", - "text": "Go to the Trading Engine layers manager on the charts (the second counting from the left). Scroll down and turn on the Limit Buy Orders layer. Now swipe the mouse pointer over a few of the buy orders and check the effect on the nodes on the design space." + "text": "Go to the Trading Engine layers manager on the charts (the second counting from the left). Scroll down and turn on the Limit Buy Orders layer. Now swipe the mouse pointer over a few of the buy orders and check the effect on the nodes on the design space.", + "translations": [ + { + "language": "IT", + "text": "Vai al layer manager del Trading Engine sul grafico (il secondo da sinistra). Scorri verso il basso e attiva il layer dei Limit Buy Orders. Ora passa con il mouse su alcuni dei buy orders e osserva l'effetto sui nodi nel Design Space.", + "updated": 1618068248928 + } + ] }, { "style": "Text", - "text": "Can you envision the implications of having this level of control over the data managed by the trading bot?" + "text": "Can you envision the implications of having this level of control over the data managed by the trading bot?", + "translations": [ + { + "language": "IT", + "text": "Capisci le implicazioni di avere un tale livello di controllo sui dati su cui lavora il Trading Bot?", + "updated": 1618068321644 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-086-tutorial-step-welcome-backtesting-trading-engine-visualization-02.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-086-tutorial-step-welcome-backtesting-trading-engine-visualization-02.json index e1a942a7b..e625c08c5 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-086-tutorial-step-welcome-backtesting-trading-engine-visualization-02.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-086-tutorial-step-welcome-backtesting-trading-engine-visualization-02.json @@ -3,7 +3,14 @@ "pageNumber": 86, "type": "Tutorial Step - Welcome Backtesting Trading Engine Visualization 02", "definition": { - "text": "This step will play a video in full screen mode." + "text": "This step will play a video in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo step riprodurrà un video a schermo intero.", + "updated": 1618068335719 + } + ] }, "paragraphs": [ { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-087-tutorial-step-enough-chit-chat.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-087-tutorial-step-enough-chit-chat.json index 4bb5250c9..98380f7f9 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-087-tutorial-step-enough-chit-chat.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-087-tutorial-step-enough-chit-chat.json @@ -7,30 +7,72 @@ "project": "Superalgos", "name": "production-trading-tasks" }, - "text": "Ok, my friend... It's time for the real deal! Are you ready for a little Live Trading Session?" + "text": "Ok, my friend... It's time for the real deal! Are you ready for a little Live Trading Session?", + "translations": [ + { + "language": "IT", + "text": "Ok, amico mio...è ora di entrare in azione! Sei pronto a una piccola Live Trading Session?", + "updated": 1618068381473 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "I'll help you with the three main requirements:" + "text": "I'll help you with the three main requirements:", + "translations": [ + { + "language": "IT", + "text": "Ti aiuterò con i tre requisiti principali:", + "updated": 1618068402523 + } + ] }, { "style": "List", - "text": "Check your parameters, in particular, decide how much capital you wish to assign to the session." + "text": "Check your parameters, in particular, decide how much capital you wish to assign to the session.", + "translations": [ + { + "language": "IT", + "text": "Controlla i parametri: in particolar modo decidi bene quanto capitale assegnare alla sessione", + "updated": 1618068548173 + } + ] }, { "style": "List", - "text": "Set up an Exchange Account Key so that the app may access your account at the exchange." + "text": "Set up an Exchange Account Key so that the app may access your account at the exchange.", + "translations": [ + { + "language": "IT", + "text": "Prepara un Exchange Account Key: necessaria perchè l'app possa accedere al tuo account sull'exchange.", + "updated": 1618068559526 + } + ] }, { "style": "List", "text": "Ensure a live data feed, that is, the data mining operation with the indicators required by the Trading System must be running and up to date.", - "updated": 1610642474628 + "updated": 1610642474628, + "translations": [ + { + "language": "IT", + "text": "Garantisci un live data feed: l'operazione di data mining con gli indicatori richiesti dal Trading System deve essere attiva e aggiornata.", + "updated": 1618068565912 + } + ] }, { "style": "Note", "text": "If you are not ready to do some live trading for whatever reason, no worries, just keep going.", - "updated": 1610642653006 + "updated": 1610642653006, + "translations": [ + { + "language": "IT", + "text": "Se per un qualunque motivo non sei pronto a fare live trading, non preccuparti! Prosegui pure.", + "updated": 1618068597799 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-088-tutorial-step-disclaimer.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-088-tutorial-step-disclaimer.json index 4d5605e68..85ee732e3 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-088-tutorial-step-disclaimer.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-088-tutorial-step-disclaimer.json @@ -3,12 +3,26 @@ "pageNumber": 88, "type": "Tutorial Step - Disclaimer", "definition": { - "text": "This warning will be rendered in full screen mode." + "text": "This warning will be rendered in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo warning verrà visualizzato a schermo intero.", + "updated": 1618069224090 + } + ] }, "paragraphs": [ { "style": "Warning", - "text": "Superalgos is a piece of computer software. Like with any software, errors may occur at any point, including errors that may cause you to lose money. You are responsible for taking all precautions you may deem appropriate before trading live. Even if you take all possible precautionary measures, things may still go wrong and errors may occur. By using this software to trade live despite the warnings, you acknowledge that you are aware of the inherent risks in trading and in using software for that purpose. The Superalgos Project offers the software AS IS, with no explicit or implied warranties of any kind. The project, the software, the superalgos.org website, and this tutorial do not offer financial advice. Although the strategies shipping with the system may be fully functional, Superalgos does not make any express or implied recommendation as to how you should use them. We share strategies for educational purposes only. Trade under your responsibility and at your own risk. The use of the software is subject to the terms of the LICENSE." + "text": "Superalgos is a piece of computer software. Like with any software, errors may occur at any point, including errors that may cause you to lose money. You are responsible for taking all precautions you may deem appropriate before trading live. Even if you take all possible precautionary measures, things may still go wrong and errors may occur. By using this software to trade live despite the warnings, you acknowledge that you are aware of the inherent risks in trading and in using software for that purpose. The Superalgos Project offers the software AS IS, with no explicit or implied warranties of any kind. The project, the software, the superalgos.org website, and this tutorial do not offer financial advice. Although the strategies shipping with the system may be fully functional, Superalgos does not make any express or implied recommendation as to how you should use them. We share strategies for educational purposes only. Trade under your responsibility and at your own risk. The use of the software is subject to the terms of the LICENSE.", + "translations": [ + { + "language": "IT", + "text": "Superalgos è un software. Come ogni altro software, può presentare errori di qualsiasi tipo, inclusi errori che possono causare all'utente perdita di denaro. Sei responsabile di prendere ogni precauzione che tu ritenga appropriata prima di fare trading live. Anche prendendo ogni precauzione possibile, è comunque possibile che si verifichino errori. Utilizzando questo software per fare trading live, nonostante i presenti avvertimenti, riconosci di essere a conoscenza dei rischi inerenti all'attività di trading e all'uso di un software per quello scopo. Superalgos Project offre il software \"AS IS\", senza alcun tipo di garanzia esplicita o implicita. Il progetto, il software, il sito superalgos.org e questo tutorial non offrono consulenza finanziaria. Nonostante le strategie incluse nel sistema possano essere funzionanti, Superalgos non fa alcuna raccomandazione esplicita o implicita su come usarle. Condividiamo strategia a puro scopo educativo. Fai trading sotto la tua responsabilità e a tuo rischio e pericolo. L'uso del software è soggetto ai termini di licenza.", + "updated": 1618069837996 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-089-tutorial-step-lets-start-with-100-bucks.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-089-tutorial-step-lets-start-with-100-bucks.json index b96bf271a..032fb847e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-089-tutorial-step-lets-start-with-100-bucks.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-089-tutorial-step-lets-start-with-100-bucks.json @@ -7,16 +7,37 @@ "project": "Superalgos", "name": "session-quoted-asset" }, - "text": "The default initialBalance is set to 100 USDT, well above the minimum transaction size supported by Binance." + "text": "The default initialBalance is set to 100 USDT, well above the minimum transaction size supported by Binance.", + "translations": [ + { + "language": "IT", + "text": "Il capitale iniziale initialBalance è impostato a 100 USDT, ben al di sopra del limite minimo per transazione supportato da Binance.", + "updated": 1618069933006 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "The initialBalance is defined in the configuration of the Session Quoted Asset. Check it out and decide for yourself if you wish to change it!" + "text": "The initialBalance is defined in the configuration of the Session Quoted Asset. Check it out and decide for yourself if you wish to change it!", + "translations": [ + { + "language": "IT", + "text": "initialBalance è definito nella configurazione del Session Quoted Asset. Esaminalo e decidi pure se preferisci cambiarlo!", + "updated": 1618069983048 + } + ] }, { "style": "Success", - "text": "Binance defines the minimum transaction size in BTC, so the requirement in USDT varies a lot with time. I set the amount to 100 USDT just to ensure you don't run into errors. You are free to try with a smaller amount. You will get errors if it's too small but may try again as many times as needed. Just stop the task, change the initialBalance in the Session Quoted Asset, and try again!" + "text": "Binance defines the minimum transaction size in BTC, so the requirement in USDT varies a lot with time. I set the amount to 100 USDT just to ensure you don't run into errors. You are free to try with a smaller amount. You will get errors if it's too small but may try again as many times as needed. Just stop the task, change the initialBalance in the Session Quoted Asset, and try again!", + "translations": [ + { + "language": "IT", + "text": "Binance definisce il valore minimo di una transazione in BTC, quindi il corrispondente valore in USDT varia molto nel tempo. Sei libero di provare con un importo minore dei 100 USDT iniziali. Riceverai un errore se l'importo è troppo piccolo, ma puoi provare di nuovo quante volte vuoi. Basta fermare la task, cambiare initialBalance nel Session Quoted Asset e riprovare!", + "updated": 1618070211585 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-090-tutorial-step-check-your-spot-balance.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-090-tutorial-step-check-your-spot-balance.json index 4c26e97b2..2a3050ba8 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-090-tutorial-step-check-your-spot-balance.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-090-tutorial-step-check-your-spot-balance.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "binance" }, - "text": "Before you run the Live Trading Session, make sure you have enough spot USDT balance at the exchange!" + "text": "Before you run the Live Trading Session, make sure you have enough spot USDT balance at the exchange!", + "translations": [ + { + "language": "IT", + "text": "Prima di lanciare la Live Trading Session, assicurati di avere abbastanza USDT nel tuo wallet spot sull'exchange.", + "updated": 1618070262891 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Take a look at your balance at the exchange and arrange for enough USDT for the session!" + "text": "Take a look at your balance at the exchange and arrange for enough USDT for the session!", + "translations": [ + { + "language": "IT", + "text": "Controlla il tuo saldo sull'exchange e prepara abbastanza USDT per la sessione!", + "updated": 1618070327486 + } + ] }, { "style": "Important", - "text": "The Trading Bot will place one limit order for the initialBalance, and cancel it the next minute in case it is not filled, as explained earlier." + "text": "The Trading Bot will place one limit order for the initialBalance, and cancel it the next minute in case it is not filled, as explained earlier.", + "translations": [ + { + "language": "IT", + "text": "Il Trading Bot inserirà un limit order del valore di initialBalance, e lo cancellerà il minuto successivo se non viene evaso, come spiegato prima.", + "updated": 1618070448288 + } + ] }, { "style": "Note", "text": "Keep going even if you are not ready to trade. You'll learn a few more tricks before we finish.", - "updated": 1616431994687 + "updated": 1616431994687, + "translations": [ + { + "language": "IT", + "text": "Continua il tutorial anche se non sei pronto al live trading. Imparerai altri trucchi utili prima della fine.", + "updated": 1618070434600 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-091-tutorial-step-enjoy-the-outdoors.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-091-tutorial-step-enjoy-the-outdoors.json index 3fcc75af1..cf5ab1f8e 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-091-tutorial-step-enjoy-the-outdoors.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-091-tutorial-step-enjoy-the-outdoors.json @@ -8,28 +8,63 @@ "name": "crypto-ecosystem" }, "text": "The Crypto Ecosystem hierarchy is where you configure which exchanges and markets you work with, your accounts with exchanges, API keys, and so on...", - "updated": 1616434733644 + "updated": 1616434733644, + "translations": [ + { + "language": "IT", + "text": "La gerarchia del Crypto Ecosystem è dove configuri con quali exchange e mercati operare, i tuoi account sugli exchange, le API keys, e così via.", + "updated": 1618070565551 + } + ] }, "paragraphs": [ { "style": "Text", "text": "Talking about API Keys, when you create your Exchange API key at the exchange, consider the following:", - "updated": 1616434379469 + "updated": 1616434379469, + "translations": [ + { + "language": "IT", + "text": "A proposito di API Keys, quando crei la tua API key sull'exchange, considera quanto segue:", + "updated": 1618070606671 + } + ] }, { "style": "List", "text": "Exclusive for Superalgos: Create a key to use excusively with Superalgos. This will help you track what Superalgos does with your account and prevent conflicts with other bots you may be using.", - "updated": 1616434392105 + "updated": 1616434392105, + "translations": [ + { + "language": "IT", + "text": "Solo per Superalgos: crea una key che userai solo per Superalgos. Questo ti aiuterà a tenere traccia di ciò che Superalgos fa con il tuo account e prevenire conflitti con altri bot che magari usi.", + "updated": 1618070656250 + } + ] }, { "style": "List", "text": "No IP Restrictions: This is to avoid issues while doing the tutorial — you may add restrictions later, once you know how the system works.", - "updated": 1616434940120 + "updated": 1616434940120, + "translations": [ + { + "language": "IT", + "text": "Non mettere restrizioni sull'IP: per evitare problemi mentre fai il tutorial (puoi aggiungere le restrizioni in un secondo momento, una volta capito il funzionamento del sistema).", + "updated": 1618070764665 + } + ] }, { "style": "List", "text": "No Withdrawals: Superalgos does not yet handle funds transfers so there is no point in allowing withdrawals. Remove withdrawals for safety reasons.", - "updated": 1616434684243 + "updated": 1616434684243, + "translations": [ + { + "language": "IT", + "text": "Niente prelievi: Superalgos non gestisce ancora il trasferimento di fondi, quindi è meglio disabilitarli per ragioni di sicurezza.", + "updated": 1618070747185 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-092-tutorial-step-your-keys-your-coins.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-092-tutorial-step-your-keys-your-coins.json index 6688e2ec2..ad6f9abec 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-092-tutorial-step-your-keys-your-coins.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-092-tutorial-step-your-keys-your-coins.json @@ -8,22 +8,50 @@ "name": "exchange-account-key" }, "text": "This is where you configure your Exchange Account Key for the Live Trading Session of the Lightning Strike Trading System.", - "updated": 1610817577376 + "updated": 1610817577376, + "translations": [ + { + "language": "IT", + "text": "Qui è dove configuro le Exchange Account Key per la Live Trading Session del Lightning Strike Trading System.", + "updated": 1618070825773 + } + ] }, "paragraphs": [ { "style": "Callout", "text": "Acess the configuration and carefully enter the API Pubilic Key and the API secret key.", - "updated": 1616435074225 + "updated": 1616435074225, + "translations": [ + { + "language": "IT", + "text": "Accedi alla configurazione e inserisci attentamente la API Public Key e la API Secret Key.", + "updated": 1618070869172 + } + ] }, { "style": "Text", - "text": "Delete the default text string for each parameter first, so that no foreign character gets mixed up with the keys." + "text": "Delete the default text string for each parameter first, so that no foreign character gets mixed up with the keys.", + "translations": [ + { + "language": "IT", + "text": "Cancella prima la stringa di testo di default per ogni parametro, così da non rischiare errori inserendo le tue chiavi.", + "updated": 1618070932988 + } + ] }, { "style": "Note", "text": "The Exchange Account Key is stored in the workspace file. It is used to authenticate with the exchange when the Trading Bot deals with orders. It is never sent or stored anywhere else.", - "updated": 1616435057411 + "updated": 1616435057411, + "translations": [ + { + "language": "IT", + "text": "L'Exchange Account Key è salvata nel workspace file. È utilizzata dal Trading Bot per autenticarsi sull'exchange quando gestisce gli ordini. Non viene inviata nè salvata in nessun'altro luogo.", + "updated": 1618071006665 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-093-tutorial-step-fire-up-the-machine.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-093-tutorial-step-fire-up-the-machine.json index ad979d262..6d1af0411 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-093-tutorial-step-fire-up-the-machine.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-093-tutorial-step-fire-up-the-machine.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "data-tasks" }, - "text": "Now it's time to fire up your Data Tasks operation." + "text": "Now it's time to fire up your Data Tasks operation.", + "translations": [ + { + "language": "IT", + "text": "Ora è il momento di lanciare le tue operazioni di Data Tasks.", + "updated": 1618071030199 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Select Run All Project Data Tasks on the menu." + "text": "Select Run All Project Data Tasks on the menu.", + "translations": [ + { + "language": "IT", + "text": "Seleziona Run All Project Data Tasks dal menù.", + "updated": 1618071069199 + } + ] }, { "style": "Text", - "text": "We'll give it a few minutes to catch up with the present time. Remember, all indicators must get to 100% before we can start trading!" + "text": "We'll give it a few minutes to catch up with the present time. Remember, all indicators must get to 100% before we can start trading!", + "translations": [ + { + "language": "IT", + "text": "Aspettiamo un paio di minuti perchè si aggiorni alla data e ora correnti. Ricorda che tutti gli indicatori devono essere a 100% prima che iniziamo a fare trading!", + "updated": 1618071103032 + } + ] }, { "style": "Success", "text": "If you are not going to run the live session, you don't need to start the Data Tasks. Just keep going to learn how the process works. ", - "updated": 1610643039999 + "updated": 1610643039999, + "translations": [ + { + "language": "IT", + "text": "Se non hai intenzione di fare trading live, non è necessario lanciare la data task. Puoi semplicemente proseguire, per vedere come funziona il procedimento.", + "updated": 1618071161823 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-094-tutorial-step-are-we-ready-yet.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-094-tutorial-step-are-we-ready-yet.json index 8f126d173..1aa9877ac 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-094-tutorial-step-are-we-ready-yet.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-094-tutorial-step-are-we-ready-yet.json @@ -8,21 +8,49 @@ "name": "indicator-process-instance" }, "text": "Resistances and Supports Multi-Period-Daily to the left is the last of the processes to finish.", - "updated": 1610643083669 + "updated": 1610643083669, + "translations": [ + { + "language": "IT", + "text": "Resistances and Supports Multi-Period-Daily a sinistra è l'ultimo processo a terminare.", + "updated": 1618071215837 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "If this process is at 100%, then we are ready to go." + "text": "If this process is at 100%, then we are ready to go.", + "translations": [ + { + "language": "IT", + "text": "Se il processo è a 100%, allora siamo pronti a iniziare.", + "updated": 1618071233196 + } + ] }, { "style": "Note", - "text": "Either way, nothing catastrophic happens if you attempt to run a Live Trading Session when the required indicators are not up to date. There would be an error, and you'd be notified of the reason. So, no big deal!" + "text": "Either way, nothing catastrophic happens if you attempt to run a Live Trading Session when the required indicators are not up to date. There would be an error, and you'd be notified of the reason. So, no big deal!", + "translations": [ + { + "language": "IT", + "text": "Ad ogni modo, non succede niente di catastrofico se tenti di lanciare una Live Trading Session quando gl indicatori non sono pronti. Ti viene semplicemente notificato un errore. Nessun problema quindi!", + "updated": 1618071277306 + } + ] }, { "style": "Success", "text": "In the next step I'll ask you to start the Task and the Live Trading Session. If you choose not to, keep going with the tutorial as if you had...", - "updated": 1610643323637 + "updated": 1610643323637, + "translations": [ + { + "language": "IT", + "text": "Nel prossimo step ti chiederò di lanciare la Task e la Live Trading Session. Se non vuoi farlo, continua con il tutorial come se niente fosse.", + "updated": 1618071315670 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-095-tutorial-step-lets-do-this.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-095-tutorial-step-lets-do-this.json index a9b705550..4f25b6db9 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-095-tutorial-step-lets-do-this.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-095-tutorial-step-lets-do-this.json @@ -7,16 +7,37 @@ "project": "Superalgos", "name": "live-trading-session" }, - "text": "We've gone through the 3-point checklist and we are ready to go, so let's get on with it!" + "text": "We've gone through the 3-point checklist and we are ready to go, so let's get on with it!", + "translations": [ + { + "language": "IT", + "text": "Abbiamo completato tutti e tre i punti sulla nostra checklist e siamo pronti a partire!", + "updated": 1618071368189 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Run the Lightning Strike Task, and then run the Lightning Strike Live Trading Session to the right!" + "text": "Run the Lightning Strike Task, and then run the Lightning Strike Live Trading Session to the right!", + "translations": [ + { + "language": "IT", + "text": "Lancia la Lightning Strike Task, e poi lancia la Lightning Strike Live Trading Session a destra!", + "updated": 1618071413222 + } + ] }, { "style": "Note", - "text": "Once you run the session, the trading bot may have to wait up to 60 seconds for the last indicator to finish processing. Once it does, you will see the current date and a 0% progress notice under the Trading Process Instance, which will remain like that throughout the run." + "text": "Once you run the session, the trading bot may have to wait up to 60 seconds for the last indicator to finish processing. Once it does, you will see the current date and a 0% progress notice under the Trading Process Instance, which will remain like that throughout the run.", + "translations": [ + { + "language": "IT", + "text": "Una volta lanciata la sessione, il trading bot può dover attendere fino a 60 secondi perchè gli ultimi indicatori terminino. Una volta completati, vedrai la data corrente e un progresso dello 0% sotto la Trading Process Instance, che rimarrà così per tutta la durata della sessione.", + "updated": 1618071515418 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-096-tutorial-step-welcome-live-trading-process-progress.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-096-tutorial-step-welcome-live-trading-process-progress.json index 789a2d5c5..829a2260c 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-096-tutorial-step-welcome-live-trading-process-progress.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-096-tutorial-step-welcome-live-trading-process-progress.json @@ -3,7 +3,14 @@ "pageNumber": 96, "type": "Tutorial Step - Welcome Live Trading Process Progress", "definition": { - "text": "This step will play a video in full screen mode." + "text": "This step will play a video in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo step eseguirà un video a schermo intero.", + "updated": 1618071529941 + } + ] }, "paragraphs": [ { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-097-tutorial-step-check-your-console.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-097-tutorial-step-check-your-console.json index e831b2529..6cd16c8a1 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-097-tutorial-step-check-your-console.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-097-tutorial-step-check-your-console.json @@ -7,20 +7,48 @@ "project": "Superalgos", "name": "trading-process-instance" }, - "text": "If you don't see any errors on the Trading Process Instance, chances are everything is working fine!" + "text": "If you don't see any errors on the Trading Process Instance, chances are everything is working fine!", + "translations": [ + { + "language": "IT", + "text": "Se non vedi alcun errore sulla Trading Process Instance, probabilmente sta andando tutto bene!", + "updated": 1618071552567 + } + ] }, "paragraphs": [ { "style": "Text", - "text": "However, you may want to take a look at your console application and see if you notice anything out of the norm." + "text": "However, you may want to take a look at your console application and see if you notice anything out of the norm.", + "translations": [ + { + "language": "IT", + "text": "Comunque, puoi controllare sulla console application e vedere se noti qualcosa di anomalo.", + "updated": 1618071581430 + } + ] }, { "style": "Callout", - "text": "Take a look at your console app!" + "text": "Take a look at your console app!", + "translations": [ + { + "language": "IT", + "text": "Dai un'occhiata alla console app!", + "updated": 1618071594539 + } + ] }, { "style": "Note", - "text": "You should be able to see the alternating executions of the Candles-Volumes and Resistances-And-Support indicators, with the Low-Frequency Trading Bot" + "text": "You should be able to see the alternating executions of the Candles-Volumes and Resistances-And-Support indicators, with the Low-Frequency Trading Bot", + "translations": [ + { + "language": "IT", + "text": "Dovresti vedere le esecuzioni alternate delle Candles-Volumes e degli indicatori Resistances-And-Supports, con il Low-Frequency Trading Bot.", + "updated": 1618071644756 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-098-tutorial-step-welcome-live-trading-console.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-098-tutorial-step-welcome-live-trading-console.json index 9543c3be8..180acf8e4 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-098-tutorial-step-welcome-live-trading-console.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-098-tutorial-step-welcome-live-trading-console.json @@ -3,7 +3,14 @@ "pageNumber": 98, "type": "Tutorial Step - Welcome Live Trading Console", "definition": { - "text": "This step will play a video in full screen mode." + "text": "This step will play a video in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo step eseguirà un video a schermo intero.", + "updated": 1618071661394 + } + ] }, "paragraphs": [ { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-099-tutorial-step-is-it-working.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-099-tutorial-step-is-it-working.json index 506fa9b8b..34e4e9907 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-099-tutorial-step-is-it-working.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-099-tutorial-step-is-it-working.json @@ -8,16 +8,37 @@ "name": "binance" }, "text": "The unequivocal way to verify if things are working fine is logging on to Binance and checking your order history for BTC/USDT.", - "updated": 1616435272813 + "updated": 1616435272813, + "translations": [ + { + "language": "IT", + "text": "Il modo più sicuro per verificare che tutto sta andando bene è andare su Binance e controllare la cronologia degli ordini BTC/USDT.", + "updated": 1618071697384 + } + ] }, "paragraphs": [ { "style": "Callout", - "text": "Go to Binance and take a look at what's going on!" + "text": "Go to Binance and take a look at what's going on!", + "translations": [ + { + "language": "IT", + "text": "Vai su Binance e controlla costa sta succedendo!", + "updated": 1618071709908 + } + ] }, { "style": "Note", - "text": "At any point in time, you should see one open order and a number of canceled orders pilling up in your order history, pretty much like in the video on the next step!" + "text": "At any point in time, you should see one open order and a number of canceled orders pilling up in your order history, pretty much like in the video on the next step!", + "translations": [ + { + "language": "IT", + "text": "In qualunque momento, dovresti vedere un ordine aperto e un certo numero di ordini cancellati nella tua cronologia, come nel video al prossimo step!", + "updated": 1618071750939 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-100-tutorial-step-welcome-live-trading-binance-orders.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-100-tutorial-step-welcome-live-trading-binance-orders.json index 9c0e7f7dc..5c8a3a9b5 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-100-tutorial-step-welcome-live-trading-binance-orders.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-100-tutorial-step-welcome-live-trading-binance-orders.json @@ -3,7 +3,14 @@ "pageNumber": 100, "type": "Tutorial Step - Welcome Live Trading Binance Orders", "definition": { - "text": "This step will play a video in full screen mode." + "text": "This step will play a video in full screen mode.", + "translations": [ + { + "language": "IT", + "text": "Questo step eseguirà un video a schermo intero.", + "updated": 1618071771852 + } + ] }, "paragraphs": [ { diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-101-tutorial-step-monitoring-the-fun-way.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-101-tutorial-step-monitoring-the-fun-way.json index 9875466b1..789dd8ce4 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-101-tutorial-step-monitoring-the-fun-way.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-101-tutorial-step-monitoring-the-fun-way.json @@ -7,21 +7,49 @@ "project": "Superalgos", "name": "bullet-limit-buy-order" }, - "text": "You thought I would let you monitor the Live Trading Session watching the ugly list of orders at the exchange? No way!" + "text": "You thought I would let you monitor the Live Trading Session watching the ugly list of orders at the exchange? No way!", + "translations": [ + { + "language": "IT", + "text": "Pensavi che ti avrei lasciato monitorare la Live Trading Session controllando quella brutta lista di ordini sull'exchange? Neanche per sogno!", + "updated": 1618071826917 + } + ] }, "paragraphs": [ { "style": "Text", "text": "Superalgos produces the same kind of simulations you fell in love with for live sessions too, in realtime!", - "updated": 1616435345542 + "updated": 1616435345542, + "translations": [ + { + "language": "IT", + "text": "Superalgos produce lo stesso tipo di simulazioni di cui ti sei innamorato anche per le live sessions, e lo fa in tempo reale!", + "updated": 1618071876792 + } + ] }, { "style": "Callout", - "text": "Can you see the first few buy orders on the chart?" + "text": "Can you see the first few buy orders on the chart?", + "translations": [ + { + "language": "IT", + "text": "Vedi i primi buy orders sul grafico?", + "updated": 1618071889300 + } + ] }, { "style": "Note", - "text": "I just brought you to the present time, on the 1-minute chart. You should be able to see the latest candle forming and a few orders already. The Rate Scale is in automatic mode at both ends. Feel free to change the scales to your liking." + "text": "I just brought you to the present time, on the 1-minute chart. You should be able to see the latest candle forming and a few orders already. The Rate Scale is in automatic mode at both ends. Feel free to change the scales to your liking.", + "translations": [ + { + "language": "IT", + "text": "Ti ho appena portato al momento attuale, sul grafico da 1-min. Dovresti vedere le ultime candele che si formano e già alcuni ordini. La Rate Scale è in automatico a entrambi gli estremi: cambiala pure come preferisci.", + "updated": 1618071961435 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-102-tutorial-step-whats-next.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-102-tutorial-step-whats-next.json index 27aae02e0..9d7dead35 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-102-tutorial-step-whats-next.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-102-tutorial-step-whats-next.json @@ -7,18 +7,39 @@ "name": "help", "project": "Superalgos" }, - "text": "There are tons of things we haven't covered yet, I know! Just look around! So much stuff to see! It's mind-boggling." + "text": "There are tons of things we haven't covered yet, I know! Just look around! So much stuff to see! It's mind-boggling.", + "translations": [ + { + "language": "IT", + "text": "Lo so, ci sono migliaia di cose che non abbiamo trattato o approfondito! C'è così tanto da vedere e imparare!", + "updated": 1618072213077 + } + ] }, "paragraphs": [ { "style": "Text", "text": "I'm sure you still have tons of questions floating in your head... How do I build my own strategies? How do I measure performance? How do I build an indicator? How do I deploy a trading farm? How may I integrate with TradingView? How do I set up Telegram announcements?", - "updated": 1610711099627 + "updated": 1610711099627, + "translations": [ + { + "language": "IT", + "text": "Sono sicuro che hai ancora chissà quante domande che ti girano in testa...come costruisco le mie strategie? Come ne misuro la performance? Come costruisco un indicatore? Come configuro una trading farm? Come posso interfacciarmi con TradingView? Come configuro le notifiche Telegram?", + "updated": 1618072291773 + } + ] }, { "style": "Success", "text": "Don't worry! You'll get there my friend! There are more tutorials and a lot of reading material available! Maybe it's a good idea to give you a quick glimpse into the built-in Documentation system before I say goodbye!", - "updated": 1611579231884 + "updated": 1611579231884, + "translations": [ + { + "language": "IT", + "text": "Non preoccuparti! Imparerai tutto! Ci sono altri tutorial e tonnellate di materiale da leggere! Penso sia una buona idea mostrarti velocemente il sistema di documentazione prima di salutarci!", + "updated": 1618072351473 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-103-tutorial-step-three-minutes-to-play.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-103-tutorial-step-three-minutes-to-play.json index 0681b6a85..5b5c0f190 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-103-tutorial-step-three-minutes-to-play.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-103-tutorial-step-three-minutes-to-play.json @@ -8,23 +8,51 @@ "name": "live-trading-session", "project": "Superalgos" }, - "updated": 1610647035525 + "updated": 1610647035525, + "translations": [ + { + "language": "IT", + "text": "Ti lascio qualche minuto per divertirti con la tua live session, e quando sarai pronto passeremo ad altre cose!", + "updated": 1618071992282 + } + ] }, "paragraphs": [ { "style": "Text", "text": "Take some time to process what you've learned so far...", - "updated": 1610647327253 + "updated": 1610647327253, + "translations": [ + { + "language": "IT", + "text": "Prenditi del tempo per elaborare le cose che hai imparato finora...", + "updated": 1618072011982 + } + ] }, { "style": "Important", "text": "Once you are ready to move on, feel free to stop the Live Trading Session and Data Tasks. You may leave the session running if you wish, but I wouldn't trust my hard-earned cash to the demo strategy indefinitely!", - "updated": 1610647503331 + "updated": 1610647503331, + "translations": [ + { + "language": "IT", + "text": "Una volta che sei pronto a proseguire, sentiti libero di fermare Live Trading Session e Data Tasks. Puoi lasciarle proseguire se preferisci, ma io non affiderei a tempo indefinito i miei sudati soldi alla strategia demo!", + "updated": 1618072064872 + } + ] }, { "style": "Success", "text": "There's still a few more things I want to show you before I let you go! Bear with me!", - "updated": 1610711032226 + "updated": 1610711032226, + "translations": [ + { + "language": "IT", + "text": "Ci sono ancora un paio di cose che voglio mostrarti prima di concludere! Tieni duro!", + "updated": 1618072086072 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-104-tutorial-step-what-else-is-cooking.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-104-tutorial-step-what-else-is-cooking.json index 08a88f531..449138f1f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-104-tutorial-step-what-else-is-cooking.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-104-tutorial-step-what-else-is-cooking.json @@ -8,26 +8,61 @@ "name": "ethereum" }, "text": "Superalgos is a multi-project platform, and —after TensorFlow— the Ethereum integration is next in line...", - "updated": 1616695001060 + "updated": 1616695001060, + "translations": [ + { + "language": "IT", + "text": "Superalgos è un progetto multi-piattaforma. Dopo quella con TensorFlow, lo step successivo è l'integrazione con Ethereum.", + "updated": 1618073342659 + } + ] }, "paragraphs": [ { "style": "Text", "text": "What does integrating Ethereum mean, you ask? It means that—in future versions—you will be able to:", - "updated": 1610719381268 + "updated": 1610719381268, + "translations": [ + { + "language": "IT", + "text": "Che cosa significa integrare Ethereum? Significa che, nelle future versioni, potrai:", + "updated": 1618073374905 + } + ] }, { "style": "List", - "text": "Connect to an Ethereum node right from within Superalgos using the visual interface." + "text": "Connect to an Ethereum node right from within Superalgos using the visual interface.", + "translations": [ + { + "language": "IT", + "text": "Connetterti a un nodo Ethereum direttamente da Superalgos usando l'interfaccia grafica.", + "updated": 1618073396110 + } + ] }, { "style": "List", "text": "Mine blockchain data to access coin and contract information for all Ethereum-based projects, including De-Fi or what have you, visualizing data on the charts, building indicators, and leveraging the rest of the Superalgos infrastructure.", - "updated": 1611584299475 + "updated": 1611584299475, + "translations": [ + { + "language": "IT", + "text": "Ottenere dati on-chain e accedere a informazioni su token e contratti di tutti i progetti basati su Ethereum, inclusi quelli De-Fi, visualizzando dati sui grafici, creando indicatori e sfruttando il resto delle funzioni di Superalgos.", + "updated": 1618073500896 + } + ] }, { "style": "List", - "text": "Use the data to trade by consuming related indicators from within trading systems!" + "text": "Use the data to trade by consuming related indicators from within trading systems!", + "translations": [ + { + "language": "IT", + "text": "Usa i dati per fare trading utilizzando i relativi indicatori dal tuo trading system!", + "updated": 1618073540467 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-105-tutorial-step-spread-the-word-on-twitter.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-105-tutorial-step-spread-the-word-on-twitter.json index 000ec7929..4e253810a 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-105-tutorial-step-spread-the-word-on-twitter.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-105-tutorial-step-spread-the-word-on-twitter.json @@ -8,23 +8,51 @@ "name": "twitter" }, "text": "Making some noise on Twitter will help bring more traders to the project. More traders pushing the boundaries of the software is the best driver of evolution!", - "updated": 1610914488286 + "updated": 1610914488286, + "translations": [ + { + "language": "IT", + "text": "Condividere il progetto su Twitter aiuterà a raggiungere più traders. Più traders che utilizzano il software è il miglior modo per incentivarne l'evoluzione!", + "updated": 1618072678582 + } + ] }, "paragraphs": [ { "style": "Text", "text": "The more traders using Superalgos, the more they will drive the Community to develop ever more advanced features! This is what you need to do:", - "updated": 1610914531306 + "updated": 1610914531306, + "translations": [ + { + "language": "IT", + "text": "Più persone usano Superalgos, più spingeranno la Community a sviluppare funzionalità ancora migliori! Ecco cosa dovresti fare:", + "updated": 1618072720212 + } + ] }, { "style": "Callout", "text": "Go to our Twitter page, follow us, and retweet our latest tweet. Make sure you tag traders you follow!", - "updated": 1610961950814 + "updated": 1610961950814, + "translations": [ + { + "language": "IT", + "text": "Vai sulla nostra page di Twitter, seguici e ritwitta il nostro ultimo tweet. Assicurati di taggare i traders che segui!", + "updated": 1618072761967 + } + ] }, { "style": "Text", "text": "That's it! No big deal, right? We appreciate your help and wish you some happy and prosperous trading!", - "updated": 1610957777183 + "updated": 1610957777183, + "translations": [ + { + "language": "IT", + "text": "Ottimo! Apprezziamo molto il tuo aiuto e ti auguriamo un trading felice e remunerativo!", + "updated": 1618072801199 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-106-tutorial-step-back-to-work.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-106-tutorial-step-back-to-work.json index fb4b5c853..95f758ea1 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-106-tutorial-step-back-to-work.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-106-tutorial-step-back-to-work.json @@ -8,23 +8,51 @@ "icon": { "name": "status-dependency", "project": "Superalgos" - } + }, + "translations": [ + { + "language": "IT", + "text": "Superalgos è provvisto di una documentazione in-app, editabile e multilingua, e addirittura di una command line! Impara a usare questi strumenti e sarai a cavallo!", + "updated": 1618072460548 + } + ] }, "paragraphs": [ { "style": "Text", "text": "You've already used a couple of documentation pages on the Docs panel on the right, but that's just the tip of the iceberg!", - "updated": 1616694225866 + "updated": 1616694225866, + "translations": [ + { + "language": "IT", + "text": "Hai già utilizzato un paio di pagine della documentazione nel pannello Docs a destra, ma è solo la punta dell'iceberg!", + "updated": 1618072487694 + } + ] }, { "style": "Callout", "text": "Let's try it! Search for the word... network.", - "updated": 1610648926126 + "updated": 1610648926126, + "translations": [ + { + "language": "IT", + "text": "Proviamo! Cerca la parola \"network\".", + "updated": 1618072499244 + } + ] }, { "style": "Success", "text": "Not to brag, but the speed of the search engine rivals the likes of Google ;-)", - "updated": 1610651624723 + "updated": 1610651624723, + "translations": [ + { + "language": "IT", + "text": "Non per vantarmi, ma la velocità del motore di ricerca fa concorrenza a Google ;-)", + "updated": 1618072524938 + } + ] }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-107-tutorial-step-tabbed-search-results.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-107-tutorial-step-tabbed-search-results.json index 4a600c8b2..2397404a9 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-107-tutorial-step-tabbed-search-results.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-107-tutorial-step-tabbed-search-results.json @@ -8,52 +8,122 @@ "icon": { "name": "dataset", "project": "Superalgos" - } + }, + "translations": [ + { + "language": "IT", + "text": "I risultati sono organizzati in categorie, e ogni categoria è rappresentata da un tab che raggruppa i risultati che corrispondono alla categoria...", + "updated": 1618072849624 + } + ] }, "paragraphs": [ { "style": "Text", "text": "I'll explain each briefly and set you free to look around:", - "updated": 1610712854590 + "updated": 1610712854590, + "translations": [ + { + "language": "IT", + "text": "Ti spiego al volo quanto basta per orientarti:", + "updated": 1618072878367 + } + ] }, { "style": "List", - "text": "All: features results from all categories." + "text": "All: features results from all categories.", + "translations": [ + { + "language": "IT", + "text": "All: risultati da ogni categoria", + "updated": 1618072897216 + } + ] }, { "style": "List", "text": "Nodes: Node Type matches containing the phrase.", - "updated": 1616694586239 + "updated": 1616694586239, + "translations": [ + { + "language": "IT", + "text": "Nodes: un tipo di nodo corrisponde alla frase", + "updated": 1618072910891 + } + ] }, { "style": "List", "text": "Concepts: includes notions such as References.", - "updated": 1610712970644 + "updated": 1610712970644, + "translations": [ + { + "language": "IT", + "text": "Concepts: include concetti come le References", + "updated": 1618072928787 + } + ] }, { "style": "List", "text": "Topics: large themes covered in sequenced pages.", - "updated": 1610712670894 + "updated": 1610712670894, + "translations": [ + { + "language": "IT", + "text": "Topics: temi estesi trattati da sequenze di pagine", + "updated": 1618072951866 + } + ] }, { "style": "List", "text": "Tutorials: features the pages that make up tutorials.", - "updated": 1610652329836 + "updated": 1610652329836, + "translations": [ + { + "language": "IT", + "text": "Tutorials: contiene le pagine che formano i tutorial", + "updated": 1618072968448 + } + ] }, { "style": "List", "text": "Reviews: features users reviews on plugins , etc...", - "updated": 1610712626605 + "updated": 1610712626605, + "translations": [ + { + "language": "IT", + "text": "Reviews: contiene le reviews degli utenti su vari temi", + "updated": 1618072989751 + } + ] }, { "style": "List", "text": "Books: collections of topics organized in chapters that cover entire app domains, for an orderly read.", - "updated": 1610712723851 + "updated": 1610712723851, + "translations": [ + { + "language": "IT", + "text": "Books: collezioni di topic organizzati in capitoli che coprono intere funzionalità del software", + "updated": 1618073039515 + } + ] }, { "style": "List", "text": "Workspace: returns nodes that are present in the active workspace... click to go to them!", - "updated": 1610713053382 + "updated": 1610713053382, + "translations": [ + { + "language": "IT", + "text": "Workspace: mostra i nodi presenti nel workspace corrente. Clicca per raggungerli!", + "updated": 1618073062614 + } + ] }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-108-tutorial-step-a-couple-more-things.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-108-tutorial-step-a-couple-more-things.json index 374193f3c..b54b0756a 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-108-tutorial-step-a-couple-more-things.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-108-tutorial-step-a-couple-more-things.json @@ -8,23 +8,51 @@ "icon": { "name": "strategy-counters", "project": "Superalgos" - } + }, + "translations": [ + { + "language": "IT", + "text": "Mancano ancora un paio di cose prima che ci salutiamo! Coraggio!", + "updated": 1618073095923 + } + ] }, "paragraphs": [ { "style": "List", "text": "I'll give you a quick introduction on what we are working on for upcoming versions of Superalgos! I mentioned Machine Learning algorithms, but there's more! It has to do with integrating crypto projects!", - "updated": 1611583731733 + "updated": 1611583731733, + "translations": [ + { + "language": "IT", + "text": "Ti dò un'introduzione rapida di ciò su cui stiamo lavorando per la prossima versione. Ho menzionato algoritmi di Machine Learning, ma c'è di più! Riguarda l'integrazione con dei progetti crypto!", + "updated": 1618073169920 + } + ] }, { "style": "List", "text": "I also want to let you know that—if you appreciate what we are doing—you can help! Tens of thousands of hours of hard work have gone into building Superalgos and bringing it to its current state. I hope you can take a couple of minutes of your time to give back, and I'll be happy to tell you where to start!", - "updated": 1611584131359 + "updated": 1611584131359, + "translations": [ + { + "language": "IT", + "text": "Volevo anche dirti che, se apprezzi ciò che stiamo facendo, ci puoi aiutare! Decine di migliaia di ore e duro lavoro sono state impiegte per costruire Superalgos così come lo vedi ora. Spero che vorrai contribuire anche solo con qualche minuto, e sarò felice di farti vedere da dove iniziare!", + "updated": 1618073272368 + } + ] }, { "style": "Success", "text": "Let's get on with it!", - "updated": 1611584148459 + "updated": 1611584148459, + "translations": [ + { + "language": "IT", + "text": "Coraggio, ti faccio vedere!", + "updated": 1618073296750 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-109-tutorial-step-help-us-with-a-star.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-109-tutorial-step-help-us-with-a-star.json index aa051966e..aa7a5523f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-109-tutorial-step-help-us-with-a-star.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-109-tutorial-step-help-us-with-a-star.json @@ -8,23 +8,51 @@ "icon": { "name": "github", "project": "Superalgos" - } + }, + "translations": [ + { + "language": "IT", + "text": "Dare a Superalgos una stella su GitHub migliora il suo ranking nella ricerca delle repo sul sito, e aiuta più sviluppatori a trovarci!", + "updated": 1618073606346 + } + ] }, "paragraphs": [ { "style": "Text", "text": "This token of appreciation is not only welcomed by the whole Community, but helps you directly too! The more developers contribute to the project, the better Superalgos gets, and the better it may serve you... so it's a no-brainer!", - "updated": 1611587542411 + "updated": 1611587542411, + "translations": [ + { + "language": "IT", + "text": "Questo gesto di apprezzamento non aiuta solo l'intera Community, ma anche te! Più sviluppatori contribuiscono al progetto, migliore Superalgos diventa, e meglio può servire ai tuoi scopi!", + "updated": 1618073681997 + } + ] }, { "style": "Callout", "text": "Just go back to our repository and click the Star button on the top-right corner!", - "updated": 1611584840715 + "updated": 1611584840715, + "translations": [ + { + "language": "IT", + "text": "Torna semplicemente al nostro repository e clicca il bottone a forma di stella nell'angolo in alto a destra!", + "updated": 1618073720679 + } + ] }, { "style": "Link", "text": "Here's a link for your convenience! Thank you!->github.com/Superalgos/Superalgos", - "updated": 1611584996191 + "updated": 1611584996191, + "translations": [ + { + "language": "IT", + "text": "Ecco il link, per comodità! Grazie mille!->github.com/Superalgos/Superalgos", + "updated": 1618073740398 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-110-tutorial-step-get-in-touch.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-110-tutorial-step-get-in-touch.json index a97eb5b51..da615ba58 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-110-tutorial-step-get-in-touch.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-110-tutorial-step-get-in-touch.json @@ -8,7 +8,14 @@ "name": "telegram-bot" }, "text": "We strive to help users progress fast and push the boundaries of what is possible with Superalgos! Join the conversation in the...", - "updated": 1610957615235 + "updated": 1610957615235, + "translations": [ + { + "language": "IT", + "text": "Mettiamo il massimo impegno nell'aiutare gli utenti a migliorare e ridefinire il concetto di cosa sia possibile fare con Superalgos! Unisciti alla conversazione...", + "updated": 1618073819599 + } + ] }, "paragraphs": [ { @@ -28,7 +35,14 @@ { "style": "Callout", "text": "Join the Announcements Channel to be the first to know about new releases, hot fixes, and important issues!", - "updated": 1610964709408 + "updated": 1610964709408, + "translations": [ + { + "language": "IT", + "text": "Unisciti agli Announcements Channel per essere sempre al corrente di nuove release, hot fix e aggiornamenti importanti!", + "updated": 1618073910521 + } + ] }, { "style": "Text", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-111-tutorial-step-ready-for-more-tutorials.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-111-tutorial-step-ready-for-more-tutorials.json index 3c2da859d..a8969e434 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-111-tutorial-step-ready-for-more-tutorials.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-111-tutorial-step-ready-for-more-tutorials.json @@ -8,23 +8,51 @@ "name": "tutorial" }, "text": "Not to brag, but I can't stress enough how important it is that you make all tutorials available before venturing on your own!", - "updated": 1610984910896 + "updated": 1610984910896, + "translations": [ + { + "language": "IT", + "text": "Non voglio stressarti, ma non smetterò mai di ripetere quanto sia importante che tu segua tutti i tutorial prima di avventurarti da solo!", + "updated": 1618074463758 + } + ] }, "paragraphs": [ { "style": "Text", "text": "The system is vast and covers complex matters. Going solo on your first days with Superalgos is only recommended for people who enjoy banging their heads against the wall!", - "updated": 1610956232418 + "updated": 1610956232418, + "translations": [ + { + "language": "IT", + "text": "Il sistema è enorme e copre concetti complessi. Iniziare avventurandosi da solo in Superalgos è raccomandato solo a coloro a cui piace finire per sbattere la testa contro il muro!", + "updated": 1618074517616 + } + ] }, { "style": "Success", "text": "The First Steps Tutorials book to your right provides all the details on the best way to invest your time learning Superalgos. ", - "updated": 1616706102160 + "updated": 1616706102160, + "translations": [ + { + "language": "IT", + "text": "Il First Steps Tutorials alla tua destra fornisce tutti i dettagli sul miglior modo di investire il tuo tempo per imparare Superalgos.", + "updated": 1618074583238 + } + ] }, { "style": "Note", "text": "Before you finish, I will leave you with the next best tutorial in the series!", - "updated": 1616706133031 + "updated": 1616706133031, + "translations": [ + { + "language": "IT", + "text": "Prima di terminare, ti lascio con il prossimo miglior tutorial della serie!", + "updated": 1618074621074 + } + ] } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-112-tutorial-step-my-only-friend-the-end.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-112-tutorial-step-my-only-friend-the-end.json index cb255ac8e..ce1193fd3 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-112-tutorial-step-my-only-friend-the-end.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-112-tutorial-step-my-only-friend-the-end.json @@ -7,23 +7,51 @@ "project": "Superalgos", "name": "close-stage-event" }, - "text": "Ok, my friend, this is the end! I hope you've enjoyed the show and that I've managed to get you hooked to Superalgos!" + "text": "Ok, my friend, this is the end! I hope you've enjoyed the show and that I've managed to get you hooked to Superalgos!", + "translations": [ + { + "language": "IT", + "text": "Ok amico mio, siamo alla fine! Spero ti sia goduto lo spettacolo e che sia riuscito a coinvolgerti in Superalgos!", + "updated": 1618074673420 + } + ] }, "paragraphs": [ { "style": "Text", "text": "There's no doubt in my mind that you haven't seen anything like Superalgos before, have you?", - "updated": 1611589835629 + "updated": 1611589835629, + "translations": [ + { + "language": "IT", + "text": "Sono certo che tu non abbia mai visto niente di simile a Superalgos, o sbaglio?", + "updated": 1618074705467 + } + ] }, { "style": "Callout", "text": "If you're ready to keep going, my friend the Basic Education Tutorial will complete your understanding on some basic aspects of the system you need to master before you set out to learn how to build Trading Systems!", - "updated": 1616706394194 + "updated": 1616706394194, + "translations": [ + { + "language": "IT", + "text": "Se sei pronto per continuare, il mio amico Basic Education Tutorial integrerà concetti su alcuni aspetti base del sistema che devi conoscere bene prima di costruire i Trading Systems! ", + "updated": 1618074793359 + } + ] }, { "style": "Success", "text": "We're done! Click Next to finish with me and click Play on the next tutorial when you are ready!", - "updated": 1616706565119 + "updated": 1616706565119, + "translations": [ + { + "language": "IT", + "text": "Abbiamo finito! Clicca Next per terminare e clicca Play sul tutorial successivo quando sei pronto!", + "updated": 1618074823724 + } + ] } ] } \ No newline at end of file From 67afd2c6a3db8c994e95794bd0954b30476d16eb Mon Sep 17 00:00:00 2001 From: Jason Hardy Date: Sat, 10 Apr 2021 20:26:58 -0500 Subject: [PATCH 22/32] This is my contribution to Superalgos --- ...rich-platform-for-algorithmic-trading.json | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json diff --git a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json new file mode 100644 index 000000000..7a0f02fc1 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json @@ -0,0 +1,27 @@ +{ + "review": "Superalgos Project Review", + "pageNumber": 7, + "type": "Superalgos Review - Feature-rich platform for algorithmic trading", + "definition": { + "text": "Write a summary for this review page." + }, + "paragraphs": [ + { + "style": "Text", + "text": "Superalgos requires a bit of patience and attention to gain an understanding of the fundamental concepts. Look at me, I'm still learning them! A background in programming is helpful, but not necessary to execute successful strategies. ", + "updated": 1618097798299 + }, + { + "style": "Text", + "text": "One things that the project has going for it is a faithful and dedicated community of developers who are open to input and quick to turn ideas into reality. I reported an issue through the community discussion group, asking for advice, and within a week the issue was resolved in the next release of code!" + }, + { + "style": "Text", + "text": "The capabilities that this open-source project have built-in are superior to some of the paid tools I had looked into before giving SA a whirl. The framework that an open-sourced project provides really means the capabilities are somewhat limitless." + }, + { + "style": "Text", + "text": "raubot" + } + ] +} \ No newline at end of file From 9e8b758c39ccd5b862bf3fb5302dddc967039ad5 Mon Sep 17 00:00:00 2001 From: Julian Molina Date: Sun, 11 Apr 2021 10:46:14 +0200 Subject: [PATCH 23/32] Update welcome-to-superalgos-062-tutorial-step-machines-learn-too.json --- ...me-to-superalgos-062-tutorial-step-machines-learn-too.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json index 883f429c1..397448c74 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-062-tutorial-step-machines-learn-too.json @@ -4,7 +4,7 @@ "type": "Tutorial Step - Machines Learn Too!", "definition": { "icon": { - "name": "learning-tasks", + "name": "tensorflow-project", "project": "Superalgos" }, "text": "The latest version of Superalgos features an experimental integration of TensorFlow to leverage ML from within the app!", @@ -55,4 +55,4 @@ ] } ] -} \ No newline at end of file +} From 48d084e2b3481407fcd8678d3040d9e7342dcc35 Mon Sep 17 00:00:00 2001 From: brycey12 Date: Sun, 11 Apr 2021 23:04:52 +1000 Subject: [PATCH 24/32] My Superalgos Review --- ...07-superalgos-review-initial-thoughts.json | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-initial-thoughts.json diff --git a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-initial-thoughts.json b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-initial-thoughts.json new file mode 100644 index 000000000..ebee11908 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-initial-thoughts.json @@ -0,0 +1,24 @@ +{ + "review": "Superalgos Project Review", + "pageNumber": 7, + "type": "Superalgos Review - Initial Thoughts", + "definition": { + "text": "My initial thoughts on Superalgos.", + "updated": 1618134889544 + }, + "paragraphs": [ + { + "style": "Text", + "text": "The first thought that came to my mind was how well documented, polished and presented Superalgos is. Considering the shear amount of knowledge to be conveied to a new user, the tutorials move at a the right pace as to not overwhelm.", + "updated": 1618134839988 + }, + { + "style": "Text", + "text": "Having written my own basic trading interface and bots using python, I look forward to not having to worry about software edge cases or outcomes I hadn't considered. Only through the work of a focussed community team can these issues be effectivly solved." + }, + { + "style": "Text", + "text": "Wish I'd found this earlier. Can't wait to dig in. " + } + ] +} \ No newline at end of file From 916562f632b7a3672ad92c0a25192895db19044c Mon Sep 17 00:00:00 2001 From: Julian Molina Date: Sun, 11 Apr 2021 18:59:48 +0200 Subject: [PATCH 25/32] Contribute tutorial plugins-docs branch update --- .../how-to/create-plugins-docs-branch-01.png | Bin 0 -> 200149 bytes .../how-to/create-plugins-docs-branch-02.png | Bin 0 -> 207718 bytes .../how-to/create-plugins-docs-branch-03.png | Bin 0 -> 189274 bytes .../Plugins/Workspaces/Getting-Started.json | 2 +- ...-the-plugins-docs-branch-in-old-forks.json | 84 ++++++++++++++++++ ...-008-tutorial-step-switching-branches.json | 12 +-- ...-tutorial-step-now-the-current-branch.json | 15 ++-- ...s-010-tutorial-step-before-you-switch.json | 16 ++-- ...lgos-011-tutorial-step-double-trouble.json | 8 +- ...012-tutorial-step-lets-switch-already.json | 4 +- ...ralgos-013-tutorial-step-welcome-back.json | 8 +- ...7.5-tutorial-step-repository-branches.json | 33 +++++++ 12 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png create mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-02.png create mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-03.png create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/how-to-003-create-the-plugins-docs-branch-in-old-forks.json create mode 100644 Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-7.5-tutorial-step-repository-branches.json diff --git a/Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png b/Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png new file mode 100644 index 0000000000000000000000000000000000000000..896944d887b434480179ad47ae695e7d88dc5dbe GIT binary patch literal 200149 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

hh_*N&%wk5 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ìX+7@eAx@Nu3LCwtE$Przj(UCICZHWR3 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


umSrmst4v*ht$EI_qJJvE()?jk` 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

hh_*N&%wk5 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�wI!$ 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 P)plugins-docs in the Field", + "updated": 1618156956365 + }, + { + "style": "Important", + "text": "Make sure the spelling is exact!" + }, + { + "style": "Json", + "text": "plugins-docs" + }, + { + "style": "Title", + "text": "4. Click the Create branch: plugins-docs from 'master' Button", + "updated": 1618156987815 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/how-to/create-plugins-docs-branch-02.png", + "updated": 1618157499323 + }, + { + "style": "Text", + "text": "You should end up with the confirmation that the new branch has been created.", + "updated": 1618157121114 + }, + { + "style": "Png", + "text": "PNGs/Superalgos/Docs/how-to/create-plugins-docs-branch-03.png", + "updated": 1618157524877 + }, + { + "style": "Title", + "text": "5. That's it!" + }, + { + "style": "Success", + "text": "Now you may go back to the tutorial!" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-008-tutorial-step-switching-branches.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-008-tutorial-step-switching-branches.json index 7d8b4e9c0..4342c737f 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-008-tutorial-step-switching-branches.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-008-tutorial-step-switching-branches.json @@ -3,8 +3,8 @@ "pageNumber": 8, "type": "Tutorial Step - Switching Branches", "definition": { - "text": "The master branch in the Superalgos repo features the latest stable version, while the develop branch features the version in development!", - "updated": 1616759979604, + "text": "Superalgos allows you to switch branches directly from within the app! But, why would you want to switch branches?", + "updated": 1618145423371, "icon": { "name": "github", "project": "Superalgos" @@ -18,13 +18,13 @@ }, { "style": "Success", - "text": "Or you may wish to submit a contribution, which must always be sent to the develop branch!", - "updated": 1616760455582 + "text": "Or you may wish to submit a contribution, like in our case right now! Let's do it!", + "updated": 1618145540691 }, { "style": "Callout", - "text": "Scroll down the Docs page to the footer and select Develop as your Contributions Branch! It's the option on the right-hand side, not in the center!", - "updated": 1616760852432 + "text": "Scroll down the Docs page to the footer and select Plugins/Docs as your Contributions Branch! It's the option on the right-hand side, not in the center!", + "updated": 1618145561816 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-009-tutorial-step-now-the-current-branch.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-009-tutorial-step-now-the-current-branch.json index 3c19006a6..5242c3ef9 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-009-tutorial-step-now-the-current-branch.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-009-tutorial-step-now-the-current-branch.json @@ -13,13 +13,18 @@ "paragraphs": [ { "style": "Text", - "text": "Now it's time to change the Current Branch! When you do that, the app will run a series of Git commands that will download the software from the develop branch of your fork! The current software will be automatically replaced on your disk! For that reason, you will need to close the app after switching, restart, find the tutorial and resume to keep going!", - "updated": 1617017990927 + "text": "Next in line is switching the Current Branch, but we need to run some checks first!", + "updated": 1618154759190 }, { - "style": "Important", - "text": "But before you switch branches, let's take a moment to think of the consequences!", - "updated": 1617008246622 + "style": "Callout", + "text": "If you forked the Superalgos repo before April 6th, 2021, follow the instructions on this page to create the plugins-docs branch. Otherwise, keep going!", + "updated": 1618154888356 + }, + { + "style": "Text", + "text": "When you switch branches, the app will run a series of Git commands that will download the software from the plugins-docs branch of your fork! The current software will be replaced on your disk! For that reason, you will need to close the app after switching. But let's discuss a couple more things before you proceed!", + "updated": 1618159009151 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-010-tutorial-step-before-you-switch.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-010-tutorial-step-before-you-switch.json index 514833ead..121481bae 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-010-tutorial-step-before-you-switch.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-010-tutorial-step-before-you-switch.json @@ -3,23 +3,23 @@ "pageNumber": 10, "type": "Tutorial Step - Before You Switch", "definition": { - "text": "There are a few things you should consider every time you switch branches! Let's go through a quick list bfore you proceed!", + "text": "There are a few things you should consider every time you switch branches! Let's go through a quick list before you proceed!", "icon": { "name": "bullet-warning", "project": "Superalgos" }, - "updated": 1617018123415 + "updated": 1618147991903 }, "paragraphs": [ { "style": "List", - "text": "It may happen that the workspaces or other data structures in the master branch are not compatible with those in the develop branch. ", - "updated": 1617017830521 + "text": "It may happen that the workspaces or other data structures in the master branch are not compatible with those in the other branch.", + "updated": 1618158546133 }, { "style": "List", - "text": "If the current workspace is incompatible with the software in the other branch, the workspace may break upon reloading the app. In such a case, you must load a Plugin Workspace of the new branch.", - "updated": 1617018153708 + "text": "If the current workspace is incompatible with the software in the other branch, the workspace may break upon reloading the app. In such a case, load one of the Plugin Workspaces of the new branch.", + "updated": 1618158600251 }, { "style": "List", @@ -28,8 +28,8 @@ }, { "style": "Important", - "text": "Always check the README file in the develop branch of the repository for any comments on backward compatibility. Before switching branches, it is always good to back up your work!", - "updated": 1617017837289 + "text": "Always check the README file in the branch of the repository you wish to access for any comments on backward compatibility. Before switching branches, back up your work!", + "updated": 1618158675366 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-011-tutorial-step-double-trouble.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-011-tutorial-step-double-trouble.json index 429974916..b3b2b4ab8 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-011-tutorial-step-double-trouble.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-011-tutorial-step-double-trouble.json @@ -13,8 +13,8 @@ "paragraphs": [ { "style": "Text", - "text": "You may have two clones of your fork running from separate folders, one of them in the develop branch.", - "updated": 1617018731051 + "text": "You may have two clones of your fork running from separate folders, each on different branches.", + "updated": 1618158812449 }, { "style": "Note", @@ -23,8 +23,8 @@ }, { "style": "Success", - "text": "Such a setup allows you to run the stable version for your production tasks, and the version in develop to contribute and test new features!", - "updated": 1617018806324 + "text": "Such a setup allows you to run the stable version for your production tasks, and the version in another branch to contribute and test new features! But you can't run two versions at the same time, unless you change ports! We won't go there now!", + "updated": 1618148172616 } ] } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-012-tutorial-step-lets-switch-already.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-012-tutorial-step-lets-switch-already.json index 67b6942ed..ace1aedfc 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-012-tutorial-step-lets-switch-already.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-012-tutorial-step-lets-switch-already.json @@ -18,8 +18,8 @@ }, { "style": "List", - "text": "Go back to the footer and select Develop as your Current Branch.", - "updated": 1617019546125 + "text": "Go back to the footer and select Plugins/Docs as your Current Branch.", + "updated": 1618159168230 }, { "style": "List", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-013-tutorial-step-welcome-back.json b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-013-tutorial-step-welcome-back.json index a69d03db3..2fda57d56 100644 --- a/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-013-tutorial-step-welcome-back.json +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/contribute-to-superalgos-013-tutorial-step-welcome-back.json @@ -3,18 +3,18 @@ "pageNumber": 13, "type": "Tutorial Step - Welcome Back!", "definition": { - "text": "If you followed my instructions to the letter, you should now be running the software in the develop branch! Awesome!", + "text": "If you followed my instructions to the letter, you should now be running the software in the plugins-docs branch! Awesome!", "icon": { "name": "hits", "project": "Superalgos" }, - "updated": 1617007379836 + "updated": 1618159282200 }, "paragraphs": [ { "style": "Text", - "text": "The software you are currently running is the version of Superalgos that was at the develop branch the day you forked the project! This is because the process of switching branches downloads the software from your fork and not the upstream repository.", - "updated": 1617020053004 + "text": "The software you are currently running is the version of Superalgos that was at the plugins-docs branch the day you forked the project! This is because the process of switching branches downloads the software from your fork and not the upstream repository.", + "updated": 1618159308510 }, { "style": "Success", diff --git a/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-7.5-tutorial-step-repository-branches.json b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-7.5-tutorial-step-repository-branches.json new file mode 100644 index 000000000..8226629b3 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Tutorials/welcome-to-superalgos-7.5-tutorial-step-repository-branches.json @@ -0,0 +1,33 @@ +{ + "tutorial": "Welcome to Superalgos!", + "pageNumber": "7.5", + "type": "Tutorial Step - Repository Branches", + "definition": { + "text": "The Superalgos repository features three main branches: master, develop, and the one we're looking for, plugins-docs.", + "icon": { + "name": "github", + "project": "Superalgos" + }, + "updated": 1618143614949 + }, + "paragraphs": [ + { + "style": "Success", + "text": "There may be more, but these are the main!", + "updated": 1618143442686 + }, + { + "style": "List", + "text": "Master Branch: Features the stable version of the software. Never submit contributions to this branch!" + }, + { + "style": "List", + "text": "Develop Branch: Features the version currently in development. Submit contributions of code affecting the codebase.", + "updated": 1618143744374 + }, + { + "style": "List", + "text": "Plugins/Docs Branch: Features the version in the master branch plus the latest changes in the Docs and Plugins. Submit contributions of translations, improvements in the Docs, tutorials, and plugins such as data mines, trading systems, and so on!" + } + ] +} \ No newline at end of file From 6c6b204072687021517a98e2d30d05b4943bbab6 Mon Sep 17 00:00:00 2001 From: Jason Hardy Date: Sun, 11 Apr 2021 16:02:25 -0500 Subject: [PATCH 26/32] This is my contribution to Superalgos --- ...rich-platform-for-algorithmic-trading.json | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json index 7a0f02fc1..a41e77928 100644 --- a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json +++ b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json @@ -3,25 +3,38 @@ "pageNumber": 7, "type": "Superalgos Review - Feature-rich platform for algorithmic trading", "definition": { - "text": "Write a summary for this review page." + "text": "The possibilities are endless when you are in control of the platform. Superalgos allows the end-user to create sophisticated trading strategies through a visual designer with built-in backtesting capabilities based on historical market data.", + "updated": 1618174871748 }, "paragraphs": [ { "style": "Text", - "text": "Superalgos requires a bit of patience and attention to gain an understanding of the fundamental concepts. Look at me, I'm still learning them! A background in programming is helpful, but not necessary to execute successful strategies. ", - "updated": 1618097798299 + "text": "After more time than I care to admit executing trades manually, I began to wonder what tools successful traders were able to leverage to quickly recognize and respond to market indicators. I started looking for a trading bot that I could leverage to make trades, but quickly realized that most of the software available today required me to give my account information to a service hosted by someone else.", + "updated": 1618174897103 }, { "style": "Text", - "text": "One things that the project has going for it is a faithful and dedicated community of developers who are open to input and quick to turn ideas into reality. I reported an issue through the community discussion group, asking for advice, and within a week the issue was resolved in the next release of code!" + "text": "Superalgos, a community-developed open-source project, does not work in that way at all. With SA, I’m able to run the software from my own device without relying on anyone else for the necessary infrastructure. I don’t need to pay a monthly subscription, and I don’t need to worry about my trading account security being at risk. " }, { "style": "Text", - "text": "The capabilities that this open-source project have built-in are superior to some of the paid tools I had looked into before giving SA a whirl. The framework that an open-sourced project provides really means the capabilities are somewhat limitless." + "text": "It does, however, require a bit of patience and attention to gain an understanding of the fundamental concepts. A familiarity with coding, particularly in Javascript, is helpful, but not necessary to execute successful strategies. The tool features an entirely visual scripting designer to help create and debug your very own strategies and indicators. Once your strategy is designed, the tool has built-in backtesting capabilities that leverage downloaded historical market data, giving you peace of mind that your strategy is fully tested before moving on to live trading. " }, { "style": "Text", - "text": "raubot" + "text": "Out of the box, there are several community-built strategies to learn from. In fact, the community is perhaps the most highly underrated feature included with the tool! A healthy set of contributors and a dedicated group of users who are willing to share and contribute their time and effort has seen this project enjoy rapid growth. " + }, + { + "style": "Text", + "text": "I have personal experience with the speed at which features can be developed, and problems can be addressed; it’s quite astonishing! As an open-sourced project, the capabilities of Superalgos are limitless." + }, + { + "style": "Text", + "text": "Thaddeus McCloud" + }, + { + "style": "Text", + "text": "raubot " } ] } \ No newline at end of file From 84cc5f30a060cacaa67f4273b7404938b908884b Mon Sep 17 00:00:00 2001 From: Jason Hardy Date: Sun, 11 Apr 2021 16:14:02 -0500 Subject: [PATCH 27/32] This is my contribution to Superalgos --- ...-review-feature-rich-platform-for-algorithmic-trading.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json index a41e77928..f7d078781 100644 --- a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json +++ b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-007-superalgos-review-feature-rich-platform-for-algorithmic-trading.json @@ -9,8 +9,8 @@ "paragraphs": [ { "style": "Text", - "text": "After more time than I care to admit executing trades manually, I began to wonder what tools successful traders were able to leverage to quickly recognize and respond to market indicators. I started looking for a trading bot that I could leverage to make trades, but quickly realized that most of the software available today required me to give my account information to a service hosted by someone else.", - "updated": 1618174897103 + "text": "After more time than I care to admit executing crypto trades manually, I began to wonder what tools successful traders were able to leverage to quickly recognize and respond to market indicators. I started looking for a trading bot that I could leverage to make trades, but quickly realized that most of the software available today required me to give my account information to a service hosted by someone else.", + "updated": 1618175562829 }, { "style": "Text", From 942f518ba599eca113b0c392f0718d9ba252db64 Mon Sep 17 00:00:00 2001 From: Smidy13 <77650800+Smidy13@users.noreply.github.com> Date: Mon, 12 Apr 2021 23:02:35 +1200 Subject: [PATCH 28/32] Revert "Bug Fix: Getting Started Tutorial Not Loading" This reverts commit daf5eb465e7ae25669b2dbaabeda48f9126790e8. --- Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js b/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js index 7272b7497..b2d119667 100644 --- a/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js +++ b/Projects/Superalgos/UI/Spaces/Tutorial-Space/TutorialSpace.js @@ -892,6 +892,7 @@ function newSuperalgosTutorialSpace() { } function playTutorial(node) { + if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return } PAGE_NUMBER = 0 TUTORIAL_NAME = node.name @@ -906,6 +907,7 @@ function newSuperalgosTutorialSpace() { } function resumeTutorial(node) { + if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return } navigationStack = [] node.payload.uiObject.isPlaying = true From 68686165c39a479864032c52c7788b2f70b28ced Mon Sep 17 00:00:00 2001 From: Smidy13 <77650800+Smidy13@users.noreply.github.com> Date: Mon, 12 Apr 2021 23:06:13 +1200 Subject: [PATCH 29/32] Social Bots Documentation Update --- .../Schemas/Docs-Nodes/social-bots.json | 18 +++++- .../Schemas/Docs-Nodes/telegram-bot.json | 58 ++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Projects/Superalgos/Schemas/Docs-Nodes/social-bots.json b/Projects/Superalgos/Schemas/Docs-Nodes/social-bots.json index e9d16292a..cf564cab2 100644 --- a/Projects/Superalgos/Schemas/Docs-Nodes/social-bots.json +++ b/Projects/Superalgos/Schemas/Docs-Nodes/social-bots.json @@ -1,3 +1,19 @@ { - "type": "Social Bots" + "type": "Social Bots", + "paragraphs": [ + { + "style": "Text", + "text": "The Social Bots node contains children nodes for each messaging bot. These messaging bots are used to configure the third party applications used to send announcements and receive incoming commands.", + "updated": 1618221943424 + }, + { + "style": "Note", + "text": "At present Superalgos only supports the Telegram messaging application.", + "updated": 1618221056200 + } + ], + "definition": { + "text": "A Social Bots node is used to define the bots for each messaging application. These messaging bots are used to send announcements and receive commands used to interact with Superalgos.", + "updated": 1618222853055 + } } \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Nodes/telegram-bot.json b/Projects/Superalgos/Schemas/Docs-Nodes/telegram-bot.json index 660294d53..7c79e785c 100644 --- a/Projects/Superalgos/Schemas/Docs-Nodes/telegram-bot.json +++ b/Projects/Superalgos/Schemas/Docs-Nodes/telegram-bot.json @@ -1,3 +1,59 @@ { - "type": "Telegram Bot" + "type": "Telegram Bot", + "paragraphs": [ + { + "style": "Text", + "text": "The Telegram Bot node is used to define the botToken and chatId parameters which are required by Superalgos to interact with the Telegram API.", + "updated": 1618224117691 + }, + { + "style": "Text", + "text": "The botToken parameter is provided by the Telegram Bot @BotFather. It is a 10 digit number, followed by a colon and then a 35 character (alpha-numeric but can also containing dash - and underscore _) string.", + "updated": 1618224138149 + }, + { + "style": "Text", + "text": "It should be contained within quotes." + }, + { + "style": "Text", + "text": "Example:", + "updated": 1618223886054 + }, + { + "style": "Javascript", + "text": "\"1234567890:aBCdE_FG4hij0kLMnoP9qrsTUvw25-xyz31\"", + "updated": 1618223916419 + }, + { + "style": "Text", + "text": "The chatId parameter is provided by the Telegram Bot @myidbot using the /getgroupid command. It is a negative 9 digit numeric number. It should be entered without quotes.", + "updated": 1618224061206 + }, + { + "style": "Text", + "text": "Example:" + }, + { + "style": "Javascript", + "text": "-123456789" + }, + { + "style": "Subtitle", + "text": "Example Configuration" + }, + { + "style": "Javascript", + "text": "{\n\t\"botToken\": \"1234567890:aBCdE_FG4hij0kLMnoP9qrsTUvw25-xyz31\",\n\t\"chatId\": -123456789\n }", + "updated": 1618224233921 + }, + { + "style": "Text", + "text": "" + } + ], + "definition": { + "text": "The Telegram Bot node is used to define the parameters used to connect to the Telegram API. This allows Superalgos to interact with Telegram to send announcements and receive incoming commands.", + "updated": 1618220722404 + } } \ No newline at end of file From 101ceb41d0bef2dfa28cdcc22f75f62f143c3122 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Apr 2021 14:25:11 +0200 Subject: [PATCH 30/32] Update CCXT library to version 1.47.49 --- .../node_modules/ccxt/CONTRIBUTING.md | 8 +- .../node_modules/ccxt/README.md | 23 +- .../ccxt/build/export-exchanges.js | 33 +- .../node_modules/ccxt/build/transpile.js | 40 +- .../node_modules/ccxt/build/vss.js | 8 +- .../node_modules/ccxt/ccxt.d.ts | 20 +- .../node_modules/ccxt/ccxt.js | 9 +- .../node_modules/ccxt/dist/ccxt.browser.js | 18251 +++++++--------- .../node_modules/ccxt/js/aax.js | 106 +- .../node_modules/ccxt/js/acx.js | 487 - .../node_modules/ccxt/js/aofex.js | 73 +- .../node_modules/ccxt/js/ascendex.js} | 158 +- .../node_modules/ccxt/js/base/Exchange.js | 315 +- .../node_modules/ccxt/js/base/Precise.js | 145 + .../ccxt/js/base/functions/encode.js | 1 - .../node_modules/ccxt/js/bibox.js | 107 +- .../node_modules/ccxt/js/bigone.js | 84 +- .../node_modules/ccxt/js/binance.js | 556 +- .../node_modules/ccxt/js/bit2c.js | 52 +- .../node_modules/ccxt/js/bitbank.js | 89 +- .../node_modules/ccxt/js/bitbay.js | 80 +- .../node_modules/ccxt/js/bitfinex.js | 278 +- .../node_modules/ccxt/js/bitfinex2.js | 241 +- .../node_modules/ccxt/js/bitflyer.js | 47 +- .../node_modules/ccxt/js/bitforex.js | 73 +- .../node_modules/ccxt/js/bitget.js | 130 +- .../node_modules/ccxt/js/bithumb.js | 136 +- .../node_modules/ccxt/js/bitmart.js | 117 +- .../node_modules/ccxt/js/bitmex.js | 111 +- .../node_modules/ccxt/js/bitpanda.js | 185 +- .../node_modules/ccxt/js/bitso.js | 79 +- .../node_modules/ccxt/js/bitstamp.js | 189 +- .../node_modules/ccxt/js/bitstamp1.js | 38 +- .../node_modules/ccxt/js/bittrex.js | 115 +- .../node_modules/ccxt/js/bitvavo.js | 137 +- .../node_modules/ccxt/js/bitz.js | 96 +- .../node_modules/ccxt/js/bl3p.js | 46 +- .../node_modules/ccxt/js/bleutrade.js | 73 +- .../node_modules/ccxt/js/braziliex.js | 69 +- .../node_modules/ccxt/js/btcalpha.js | 38 +- .../node_modules/ccxt/js/btcbox.js | 40 +- .../node_modules/ccxt/js/btcmarkets.js | 64 +- .../node_modules/ccxt/js/btctradeua.js | 24 +- .../node_modules/ccxt/js/btcturk.js | 38 +- .../node_modules/ccxt/js/buda.js | 40 +- .../node_modules/ccxt/js/bw.js | 76 +- .../node_modules/ccxt/js/bybit.js | 200 +- .../node_modules/ccxt/js/bytetrade.js | 99 +- .../node_modules/ccxt/js/cex.js | 96 +- .../node_modules/ccxt/js/chilebit.js | 32 - .../node_modules/ccxt/js/coinbase.js | 36 +- .../node_modules/ccxt/js/coinbasepro.js | 113 +- .../node_modules/ccxt/js/coincheck.js | 67 +- .../node_modules/ccxt/js/coinegg.js | 52 +- .../node_modules/ccxt/js/coinex.js | 71 +- .../node_modules/ccxt/js/coinfalcon.js | 55 +- .../node_modules/ccxt/js/coinfloor.js | 71 +- .../node_modules/ccxt/js/coingi.js | 38 +- .../node_modules/ccxt/js/coinmarketcap.js | 6 +- .../node_modules/ccxt/js/coinmate.js | 54 +- .../node_modules/ccxt/js/coinone.js | 66 +- .../node_modules/ccxt/js/coinspot.js | 25 +- .../node_modules/ccxt/js/crex24.js | 136 +- .../node_modules/ccxt/js/currencycom.js | 183 +- .../node_modules/ccxt/js/delta.js | 88 +- .../node_modules/ccxt/js/deribit.js | 84 +- .../node_modules/ccxt/js/digifinex.js | 229 +- .../node_modules/ccxt/js/dsx.js | 1274 -- .../node_modules/ccxt/js/equos.js | 58 +- .../node_modules/ccxt/js/eterbase.js | 78 +- .../node_modules/ccxt/js/exmo.js | 125 +- .../node_modules/ccxt/js/exx.js | 56 +- .../node_modules/ccxt/js/fcoin.js | 89 +- .../node_modules/ccxt/js/flowbtc.js | 34 +- .../node_modules/ccxt/js/foxbit.js | 32 +- .../node_modules/ccxt/js/ftx.js | 156 +- .../node_modules/ccxt/js/gateio.js | 108 +- .../node_modules/ccxt/js/gemini.js | 82 +- .../node_modules/ccxt/js/gopax.js | 137 +- .../node_modules/ccxt/js/hbtc.js | 104 +- .../node_modules/ccxt/js/hitbtc.js | 219 +- .../node_modules/ccxt/js/hollaex.js | 319 +- .../node_modules/ccxt/js/huobipro.js | 204 +- .../node_modules/ccxt/js/ice3x.js | 495 - .../node_modules/ccxt/js/idex.js | 83 +- .../ccxt/js/independentreserve.js | 62 +- .../node_modules/ccxt/js/indodax.js | 50 +- .../node_modules/ccxt/js/itbit.js | 68 +- .../node_modules/ccxt/js/kraken.js | 141 +- .../node_modules/ccxt/js/kucoin.js | 473 +- .../node_modules/ccxt/js/kuna.js | 405 +- .../node_modules/ccxt/js/lakebtc.js | 30 +- .../node_modules/ccxt/js/latoken.js | 97 +- .../node_modules/ccxt/js/lbank.js | 84 +- .../node_modules/ccxt/js/liquid.js | 133 +- .../node_modules/ccxt/js/luno.js | 83 +- .../node_modules/ccxt/js/lykke.js | 53 +- .../node_modules/ccxt/js/mercado.js | 71 +- .../node_modules/ccxt/js/mixcoins.js | 32 +- .../node_modules/ccxt/js/ndax.js | 117 +- .../node_modules/ccxt/js/novadax.js | 79 +- .../node_modules/ccxt/js/oceanex.js | 56 +- .../node_modules/ccxt/js/okex.js | 167 +- .../node_modules/ccxt/js/paymium.js | 38 +- .../node_modules/ccxt/js/phemex.js | 148 +- .../node_modules/ccxt/js/poloniex.js | 85 +- .../node_modules/ccxt/js/probit.js | 127 +- .../node_modules/ccxt/js/qtrade.js | 132 +- .../node_modules/ccxt/js/rightbtc.js | 56 +- .../node_modules/ccxt/js/ripio.js | 58 +- .../node_modules/ccxt/js/southxchange.js | 63 +- .../node_modules/ccxt/js/stex.js | 87 +- .../ccxt/js/test/Exchange/test.ticker.js | 1 + .../js/test/base/functions/test.number.js | 56 + .../ccxt/js/test/base/test.base.js | 2 +- .../node_modules/ccxt/js/therock.js | 60 +- .../node_modules/ccxt/js/tidebit.js | 62 +- .../node_modules/ccxt/js/tidex.js | 171 +- .../node_modules/ccxt/js/timex.js | 136 +- .../node_modules/ccxt/js/upbit.js | 99 +- .../node_modules/ccxt/js/vaultoro.js | 203 - .../node_modules/ccxt/js/vcc.js | 108 +- .../node_modules/ccxt/js/wavesexchange.js | 40 +- .../node_modules/ccxt/js/whitebit.js | 52 +- .../node_modules/ccxt/js/xbtce.js | 21 +- .../node_modules/ccxt/js/xena.js | 94 +- .../node_modules/ccxt/js/yobit.js | 97 +- .../node_modules/ccxt/js/zaif.js | 75 +- .../node_modules/ccxt/js/zb.js | 104 +- .../node_modules/ccxt/package.json | 24 +- .../Exchange-Raw-Data/package-lock.json | 6 +- .../APIs/node_modules/ccxt/CONTRIBUTING.md | 8 +- .../APIs/node_modules/ccxt/README.md | 23 +- .../ccxt/build/export-exchanges.js | 33 +- .../APIs/node_modules/ccxt/build/transpile.js | 40 +- .../APIs/node_modules/ccxt/build/vss.js | 8 +- .../APIs/node_modules/ccxt/ccxt.d.ts | 20 +- .../APIs/node_modules/ccxt/ccxt.js | 9 +- .../node_modules/ccxt/dist/ccxt.browser.js | 18251 +++++++--------- .../APIs/node_modules/ccxt/js/aax.js | 106 +- .../APIs/node_modules/ccxt/js/acx.js | 487 - .../APIs/node_modules/ccxt/js/aofex.js | 73 +- .../APIs/node_modules/ccxt/js/ascendex.js} | 158 +- .../node_modules/ccxt/js/base/Exchange.js | 315 +- .../APIs/node_modules/ccxt/js/base/Precise.js | 145 + .../ccxt/js/base/functions/encode.js | 1 - .../APIs/node_modules/ccxt/js/bibox.js | 107 +- .../APIs/node_modules/ccxt/js/bigone.js | 84 +- .../APIs/node_modules/ccxt/js/binance.js | 556 +- .../APIs/node_modules/ccxt/js/bit2c.js | 52 +- .../APIs/node_modules/ccxt/js/bitbank.js | 89 +- .../APIs/node_modules/ccxt/js/bitbay.js | 80 +- .../APIs/node_modules/ccxt/js/bitfinex.js | 278 +- .../APIs/node_modules/ccxt/js/bitfinex2.js | 241 +- .../APIs/node_modules/ccxt/js/bitflyer.js | 47 +- .../APIs/node_modules/ccxt/js/bitforex.js | 73 +- .../APIs/node_modules/ccxt/js/bitget.js | 130 +- .../APIs/node_modules/ccxt/js/bithumb.js | 136 +- .../APIs/node_modules/ccxt/js/bitmart.js | 117 +- .../APIs/node_modules/ccxt/js/bitmex.js | 111 +- .../APIs/node_modules/ccxt/js/bitpanda.js | 185 +- .../APIs/node_modules/ccxt/js/bitso.js | 79 +- .../APIs/node_modules/ccxt/js/bitstamp.js | 189 +- .../APIs/node_modules/ccxt/js/bitstamp1.js | 38 +- .../APIs/node_modules/ccxt/js/bittrex.js | 115 +- .../APIs/node_modules/ccxt/js/bitvavo.js | 137 +- .../APIs/node_modules/ccxt/js/bitz.js | 96 +- .../APIs/node_modules/ccxt/js/bl3p.js | 46 +- .../APIs/node_modules/ccxt/js/bleutrade.js | 73 +- .../APIs/node_modules/ccxt/js/braziliex.js | 69 +- .../APIs/node_modules/ccxt/js/btcalpha.js | 38 +- .../APIs/node_modules/ccxt/js/btcbox.js | 40 +- .../APIs/node_modules/ccxt/js/btcmarkets.js | 64 +- .../APIs/node_modules/ccxt/js/btctradeua.js | 24 +- .../APIs/node_modules/ccxt/js/btcturk.js | 38 +- .../APIs/node_modules/ccxt/js/buda.js | 40 +- .../APIs/node_modules/ccxt/js/bw.js | 76 +- .../APIs/node_modules/ccxt/js/bybit.js | 200 +- .../APIs/node_modules/ccxt/js/bytetrade.js | 99 +- .../APIs/node_modules/ccxt/js/cex.js | 96 +- .../APIs/node_modules/ccxt/js/chilebit.js | 32 - .../APIs/node_modules/ccxt/js/coinbase.js | 36 +- .../APIs/node_modules/ccxt/js/coinbasepro.js | 113 +- .../APIs/node_modules/ccxt/js/coincheck.js | 67 +- .../APIs/node_modules/ccxt/js/coinegg.js | 52 +- .../APIs/node_modules/ccxt/js/coinex.js | 71 +- .../APIs/node_modules/ccxt/js/coinfalcon.js | 55 +- .../APIs/node_modules/ccxt/js/coinfloor.js | 71 +- .../APIs/node_modules/ccxt/js/coingi.js | 38 +- .../node_modules/ccxt/js/coinmarketcap.js | 6 +- .../APIs/node_modules/ccxt/js/coinmate.js | 54 +- .../APIs/node_modules/ccxt/js/coinone.js | 66 +- .../APIs/node_modules/ccxt/js/coinspot.js | 25 +- .../APIs/node_modules/ccxt/js/crex24.js | 136 +- .../APIs/node_modules/ccxt/js/currencycom.js | 183 +- .../APIs/node_modules/ccxt/js/delta.js | 88 +- .../APIs/node_modules/ccxt/js/deribit.js | 84 +- .../APIs/node_modules/ccxt/js/digifinex.js | 229 +- .../APIs/node_modules/ccxt/js/dsx.js | 1274 -- .../APIs/node_modules/ccxt/js/equos.js | 58 +- .../APIs/node_modules/ccxt/js/eterbase.js | 78 +- .../APIs/node_modules/ccxt/js/exmo.js | 125 +- .../APIs/node_modules/ccxt/js/exx.js | 56 +- .../APIs/node_modules/ccxt/js/fcoin.js | 89 +- .../APIs/node_modules/ccxt/js/flowbtc.js | 34 +- .../APIs/node_modules/ccxt/js/foxbit.js | 32 +- .../APIs/node_modules/ccxt/js/ftx.js | 156 +- .../APIs/node_modules/ccxt/js/gateio.js | 108 +- .../APIs/node_modules/ccxt/js/gemini.js | 82 +- .../APIs/node_modules/ccxt/js/gopax.js | 137 +- .../APIs/node_modules/ccxt/js/hbtc.js | 104 +- .../APIs/node_modules/ccxt/js/hitbtc.js | 219 +- .../APIs/node_modules/ccxt/js/hollaex.js | 319 +- .../APIs/node_modules/ccxt/js/huobipro.js | 204 +- .../APIs/node_modules/ccxt/js/ice3x.js | 495 - .../APIs/node_modules/ccxt/js/idex.js | 83 +- .../ccxt/js/independentreserve.js | 62 +- .../APIs/node_modules/ccxt/js/indodax.js | 50 +- .../APIs/node_modules/ccxt/js/itbit.js | 68 +- .../APIs/node_modules/ccxt/js/kraken.js | 141 +- .../APIs/node_modules/ccxt/js/kucoin.js | 473 +- .../APIs/node_modules/ccxt/js/kuna.js | 405 +- .../APIs/node_modules/ccxt/js/lakebtc.js | 30 +- .../APIs/node_modules/ccxt/js/latoken.js | 97 +- .../APIs/node_modules/ccxt/js/lbank.js | 84 +- .../APIs/node_modules/ccxt/js/liquid.js | 133 +- .../APIs/node_modules/ccxt/js/luno.js | 83 +- .../APIs/node_modules/ccxt/js/lykke.js | 53 +- .../APIs/node_modules/ccxt/js/mercado.js | 71 +- .../APIs/node_modules/ccxt/js/mixcoins.js | 32 +- .../APIs/node_modules/ccxt/js/ndax.js | 117 +- .../APIs/node_modules/ccxt/js/novadax.js | 79 +- .../APIs/node_modules/ccxt/js/oceanex.js | 56 +- .../APIs/node_modules/ccxt/js/okex.js | 167 +- .../APIs/node_modules/ccxt/js/paymium.js | 38 +- .../APIs/node_modules/ccxt/js/phemex.js | 148 +- .../APIs/node_modules/ccxt/js/poloniex.js | 85 +- .../APIs/node_modules/ccxt/js/probit.js | 127 +- .../APIs/node_modules/ccxt/js/qtrade.js | 132 +- .../APIs/node_modules/ccxt/js/rightbtc.js | 56 +- .../APIs/node_modules/ccxt/js/ripio.js | 58 +- .../APIs/node_modules/ccxt/js/southxchange.js | 63 +- .../APIs/node_modules/ccxt/js/stex.js | 87 +- .../ccxt/js/test/Exchange/test.ticker.js | 1 + .../js/test/base/functions/test.number.js | 56 + .../ccxt/js/test/base/test.base.js | 2 +- .../APIs/node_modules/ccxt/js/therock.js | 60 +- .../APIs/node_modules/ccxt/js/tidebit.js | 62 +- .../APIs/node_modules/ccxt/js/tidex.js | 171 +- .../APIs/node_modules/ccxt/js/timex.js | 136 +- .../APIs/node_modules/ccxt/js/upbit.js | 99 +- .../APIs/node_modules/ccxt/js/vaultoro.js | 203 - .../APIs/node_modules/ccxt/js/vcc.js | 108 +- .../node_modules/ccxt/js/wavesexchange.js | 40 +- .../APIs/node_modules/ccxt/js/whitebit.js | 52 +- .../APIs/node_modules/ccxt/js/xbtce.js | 21 +- .../APIs/node_modules/ccxt/js/xena.js | 94 +- .../APIs/node_modules/ccxt/js/yobit.js | 97 +- .../APIs/node_modules/ccxt/js/zaif.js | 75 +- .../APIs/node_modules/ccxt/js/zb.js | 104 +- .../APIs/node_modules/ccxt/package.json | 24 +- .../APIs/package-lock.json | 6 +- 262 files changed, 29194 insertions(+), 36776 deletions(-) delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/acx.js rename Projects/Superalgos/TS/Bot-Modules/{Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmax.js => Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ascendex.js} (93%) create mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Precise.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/chilebit.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/dsx.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ice3x.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vaultoro.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/acx.js rename Projects/Superalgos/TS/Bot-Modules/{Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmax.js => Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ascendex.js} (93%) create mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Precise.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/chilebit.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/dsx.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ice3x.js delete mode 100644 Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vaultoro.js diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/CONTRIBUTING.md b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/CONTRIBUTING.md index 1d3ff05d1..7ff3d7ae6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/CONTRIBUTING.md +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/CONTRIBUTING.md @@ -261,7 +261,7 @@ These files containing derived exchange classes are transpiled from JS into PHP: These PHP base classes and files are not transpiled: -- `php/base/*` +- `php/Exchange.php php/ExchangeError.php php/Precise.php ... #### Typescript @@ -385,7 +385,7 @@ async fetchTicker (symbol, params = {}) { #### Parsing Symbols -When sending requests to the exchange unified symbols have to be _"converted"_ to exchange-specific market-`id`s like shown above. The same is true on the other side – when receiving an exchange response it has an exchange-specific market-`id` inside it that has to be _"converted back"_ to a unified CCXT symbol. +When sending requests to the exchange unified symbols have to be _"converted"_ to exchange-specific market-`id`s like shown above. The same is true on the other end – when receiving an exchange response it has an exchange-specific market-`id` inside it that has to be _"converted back"_ to a unified CCXT symbol. **We don't put exchange-specific market-`id`s in unified structures directly!** We can't freely interchange symbols with ids! There is a significant difference between an *exchange-specific market-ids* and *unified symbols*! This is explained in the Manual, here: @@ -444,7 +444,7 @@ In JavaScript, dictionary keys can be accessed in two notations: Both work almost identically, and one is implicitly converted to another upon executing the JavaScript code. -While the above does work in JavaScript, it will not work in Python or PHP. In most languages, associative dictionary keys are not treated in the same way as properties. Therefore, in Python `object.key` is not the same as `object['key']`. In PHP `$object->key` is not the same as `$object['key']` as well. Languages that differentiate between associative keys and properties use different notations for the two. +While the above does work in JavaScript, **it will not work in Python or PHP**. In most languages, associative dictionary keys are not treated in the same way as properties. Therefore, in Python `object.key` is not the same as `object['key']`. In PHP `$object->key` is not the same as `$object['key']` as well. Languages that differentiate between associative keys and properties use different notations for the two. To keep the code transpileable, please, remember this simple rule: *always use the single-quoted string key notation `object['key']` for accessing all associative dictionary keys in all languages everywhere throughout this library!* @@ -572,7 +572,7 @@ The `hmac()` method also supports `'base64'` for the `digest` argument. This is #### Timestamps -**All timestamps throughout all unified structures within this library are integer timestamp _in milliseconds_!** +**All timestamps throughout all unified structures within this library are integer UTC timestamps _in milliseconds_!** In order to convert to milliseconds timestamps, CCXT implements the following methods: diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/README.md b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/README.md index 3f8dfeea4..7ec80167e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/README.md +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/README.md @@ -1,6 +1,6 @@ # CCXT – CryptoCurrency eXchange Trading Library -[![Build Status](https://travis-ci.com/ccxt/ccxt.svg?branch=master)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/dhzSKYU) [![Supported Exchanges](https://img.shields.io/badge/exchanges-126-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Open Collective](https://opencollective.com/ccxt/backers/badge.svg)](https://opencollective.com/ccxt) +[![Build Status](https://travis-ci.com/ccxt/ccxt.svg?branch=master)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/dhzSKYU) [![Supported Exchanges](https://img.shields.io/badge/exchanges-121-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Open Collective](https://opencollective.com/ccxt/backers/badge.svg)](https://opencollective.com/ccxt) [![Twitter Follow](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://twitter.com/ccxt_official) A JavaScript / Python / PHP library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs. @@ -25,10 +25,10 @@ Current feature list: ## See Also -- [![Quadency](https://user-images.githubusercontent.com/1294454/69334382-a0618100-0c6b-11ea-9ba9-40aa97440cfa.png)](https://quadency.com?utm_source=ccxt)  **[Quadency](https://quadency.com?utm_source=ccxt)** — trading automation terminal for leading exchanges with streaming APIs + Python IDE. - [![TabTrader](https://user-images.githubusercontent.com/1294454/66755907-9c3e8880-eea1-11e9-846e-0bff349ceb87.png)](https://tab-trader.com/?utm_source=ccxt)  **[TabTrader](https://tab-trader.com/?utm_source=ccxt)** — trading on all exchanges in one app. Avaliable on [Android](https://play.google.com/store/apps/details?id=com.tabtrader.android&referrer=utm_source%3Dccxt) and [iOS](https://itunes.apple.com/app/apple-store/id1095716562?mt=8). - [![Pionex](https://user-images.githubusercontent.com/1294454/106112806-c2ec0580-615e-11eb-870c-0b7aef021db2.png)](https://www.pionex.com/en-US/sign?r=8wSFCbNk&utm_source=ad&utm_medium=banner&utm_campaign=ccxt-2)  **[Pionex](https://www.pionex.com/en-US/sign?r=8wSFCbNk&utm_source=ad&utm_medium=banner&utm_campaign=ccxt-2)** — 6 grid bots, spot-futures arb bot, smart trade and DCA bots. Free for [Android](https://play.google.com/store/apps/details?id=com.pionex.client&referrer=utm_source%3Dccxt) and [iOS](https://apps.apple.com/us/app/pionex/id1485348891?pt=ccxt&ct=inline)! - [![AAX](https://user-images.githubusercontent.com/1294454/106509642-ef957980-64de-11eb-92e0-8323cda7874e.png)](https://www.aaxpro.com/en-US/ad-sign-up/?utm_source=ccxt&utm_medium=one-liner&utm_campaign=futures)  **[AAX](https://www.aaxpro.com/en-US/ad-sign-up/?utm_source=ccxt&utm_medium=one-liner&utm_campaign=futures)** — trade bitcoin futures with fees as low as 0.02% and up to 100x leverage! +- [![Freqtrade](https://user-images.githubusercontent.com/1294454/114340585-8e35fa80-9b60-11eb-860f-4379125e2db6.png)](https://www.freqtrade.io)  **[Freqtrade](https://www.freqtrade.io)** — leading opensource cryptocurrency algorithmic trading software! ## Certified Cryptocurrency Exchanges @@ -52,13 +52,13 @@ Current feature list: ## Supported Cryptocurrency Exchange Markets -The CCXT library currently supports the following 126 cryptocurrency exchange markets and trading APIs: +The CCXT library currently supports the following 121 cryptocurrency exchange markets and trading APIs: | logo | id | name | ver | doc | certified | pro | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|-----------------------------------------------------------------------------------------|:---:|:-------------------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------| | [![aax](https://user-images.githubusercontent.com/1294454/104140087-a27f2580-53c0-11eb-87c1-5d9e81208fe9.jpg)](https://www.aaxpro.com/invite/sign-up?inviteCode=JXGm5Fy7R2MB) | aax | [AAX](https://www.aaxpro.com/invite/sign-up?inviteCode=JXGm5Fy7R2MB) | 2 | [API](https://www.aaxpro.com/apidoc/index.html) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | -| [![acx](https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg)](https://acx.io) | acx | [ACX](https://acx.io) | 2 | [API](https://acx.io/documents/api_v2) | | | | [![aofex](https://user-images.githubusercontent.com/51840849/77670271-056d1080-6f97-11ea-9ac2-4268e9ed0c1f.jpg)](https://aofex.com/#/register?key=9763840) | aofex | [AOFEX](https://aofex.com/#/register?key=9763840) | * | [API](https://aofex.zendesk.com/hc/en-us/sections/360005576574-API) | | | +| [![ascendex](https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg)](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | ascendex | [AscendEX](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | 1 | [API](https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation) | | | | [![bequant](https://user-images.githubusercontent.com/1294454/55248342-a75dfe00-525a-11e9-8aa2-05e9dca943c6.jpg)](https://bequant.io) | bequant | [Bequant](https://bequant.io) | 2 | [API](https://api.bequant.io/) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bibox](https://user-images.githubusercontent.com/51840849/77257418-3262b000-6c85-11ea-8fb8-20bdf20b3592.jpg)](https://w2.bibox365.com/login/register?invite_code=05Kj3I) | bibox | [Bibox](https://w2.bibox365.com/login/register?invite_code=05Kj3I) | 1 | [API](https://biboxcom.github.io/en/) | | | | [![bigone](https://user-images.githubusercontent.com/1294454/69354403-1d532180-0c91-11ea-88ed-44c06cefdf87.jpg)](https://b1.run/users/new?code=D3LLBVFT) | bigone | [BigONE](https://b1.run/users/new?code=D3LLBVFT) | 3 | [API](https://open.big.one/docs/api.html) | | | @@ -76,7 +76,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bithumb](https://user-images.githubusercontent.com/1294454/30597177-ea800172-9d5e-11e7-804c-b9d4fa9b56b0.jpg)](https://www.bithumb.com) | bithumb | [Bithumb](https://www.bithumb.com) | * | [API](https://apidocs.bithumb.com) | | | | [![bitkk](https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg)](https://www.bitkk.com) | bitkk | [bitkk](https://www.bitkk.com) | 1 | [API](https://www.bitkk.com/i/developer) | | | | [![bitmart](https://user-images.githubusercontent.com/1294454/61835713-a2662f80-ae85-11e9-9d00-6442919701fd.jpg)](http://www.bitmart.com/?r=rQCFLh) | bitmart | [BitMart](http://www.bitmart.com/?r=rQCFLh) | 1 | [API](https://developer-pro.bitmart.com/) | | | -| [![bitmax](https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg)](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | bitmax | [BitMax](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | 1 | [API](https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation) | | | | [![bitmex](https://user-images.githubusercontent.com/1294454/27766319-f653c6e6-5ed4-11e7-933d-f0bc3699ae8f.jpg)](https://www.bitmex.com/register/upZpOX) | bitmex | [BitMEX](https://www.bitmex.com/register/upZpOX) | 1 | [API](https://www.bitmex.com/app/apiOverview) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bitpanda](https://user-images.githubusercontent.com/51840849/87591171-9a377d80-c6f0-11ea-94ac-97a126eac3bc.jpg)](https://www.bitpanda.com/en/pro) | bitpanda | [Bitpanda Pro](https://www.bitpanda.com/en/pro) | 1 | [API](https://developers.bitpanda.com/exchange/) | | | | [![bitso](https://user-images.githubusercontent.com/51840849/87295554-11f98280-c50e-11ea-80d6-15b3bafa8cbf.jpg)](https://bitso.com/?ref=itej) | bitso | [Bitso](https://bitso.com/?ref=itej) | 3 | [API](https://bitso.com/api_info) | | | @@ -84,7 +83,7 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bitstamp1](https://user-images.githubusercontent.com/1294454/27786377-8c8ab57e-5fe9-11e7-8ea4-2b05b6bcceec.jpg)](https://www.bitstamp.net) | bitstamp1 | [Bitstamp](https://www.bitstamp.net) | 1 | [API](https://www.bitstamp.net/api) | | | | [![bittrex](https://user-images.githubusercontent.com/51840849/87153921-edf53180-c2c0-11ea-96b9-f2a9a95a455b.jpg)](https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B) | bittrex | [Bittrex](https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B) | 3 | [API](https://bittrex.github.io/api/v3) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bitvavo](https://user-images.githubusercontent.com/1294454/83165440-2f1cf200-a116-11ea-9046-a255d09fb2ed.jpg)](https://bitvavo.com/?a=24F34952F7) | bitvavo | [Bitvavo](https://bitvavo.com/?a=24F34952F7) | 2 | [API](https://docs.bitvavo.com/) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![bitz](https://user-images.githubusercontent.com/51840849/87443304-fec5e000-c5fd-11ea-98f8-ba8e67f7eaff.jpg)](https://u.bitz.com/register?invite_code=1429193) | bitz | [Bit-Z](https://u.bitz.com/register?invite_code=1429193) | 2 | [API](https://apidoc.bitz.com/en/) | | | +| [![bitz](https://user-images.githubusercontent.com/51840849/87443304-fec5e000-c5fd-11ea-98f8-ba8e67f7eaff.jpg)](https://u.bitz.com/register?invite_code=1429193) | bitz | [Bit-Z](https://u.bitz.com/register?invite_code=1429193) | 2 | [API](https://apidocv2.bitz.plus/en/) | | | | [![bl3p](https://user-images.githubusercontent.com/1294454/28501752-60c21b82-6feb-11e7-818b-055ee6d0e754.jpg)](https://bl3p.eu) | bl3p | [BL3P](https://bl3p.eu) | 1 | [API](https://github.com/BitonicNL/bl3p-api/tree/master/docs) | | | | [![bleutrade](https://user-images.githubusercontent.com/1294454/30303000-b602dbe6-976d-11e7-956d-36c5049c01e7.jpg)](https://bleutrade.com) | bleutrade | [Bleutrade](https://bleutrade.com) | * | [API](https://app.swaggerhub.com/apis-docs/bleu/white-label/3.0.0) | | | | [![braziliex](https://user-images.githubusercontent.com/1294454/34703593-c4498674-f504-11e7-8d14-ff8e44fb78c1.jpg)](https://braziliex.com/?ref=5FE61AB6F6D67DA885BC98BA27223465) | braziliex | [Braziliex](https://braziliex.com/?ref=5FE61AB6F6D67DA885BC98BA27223465) | * | [API](https://braziliex.com/exchange/api.php) | | | @@ -99,7 +98,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bytetrade](https://user-images.githubusercontent.com/1294454/67288762-2f04a600-f4e6-11e9-9fd6-c60641919491.jpg)](https://www.byte-trade.com) | bytetrade | [ByteTrade](https://www.byte-trade.com) | * | [API](https://docs.byte-trade.com/#description) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | | [![cdax](https://user-images.githubusercontent.com/1294454/102157692-fd406280-3e90-11eb-8d46-4511b617cd17.jpg)](https://cdax.io/invite?invite_code=esc74) | cdax | [CDAX](https://cdax.io/invite?invite_code=esc74) | 1 | [API](https://github.com/cloudapidoc/API_Docs) | | | | [![cex](https://user-images.githubusercontent.com/1294454/27766442-8ddc33b0-5ed8-11e7-8b98-f786aef0f3c9.jpg)](https://cex.io/r/0/up105393824/0/) | cex | [CEX.IO](https://cex.io/r/0/up105393824/0/) | * | [API](https://cex.io/cex-api) | | | -| [![chilebit](https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg)](https://chilebit.net) | chilebit | [ChileBit](https://chilebit.net) | 1 | [API](https://blinktrade.com/docs) | | | | [![coinbase](https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg)](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | coinbase | [Coinbase](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | 2 | [API](https://developers.coinbase.com/api/v2) | | | | [![coinbaseprime](https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg)](https://prime.coinbase.com) | coinbaseprime | [Coinbase Prime](https://prime.coinbase.com) | * | [API](https://docs.prime.coinbase.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![coinbasepro](https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg)](https://pro.coinbase.com/) | coinbasepro | [Coinbase Pro](https://pro.coinbase.com/) | * | [API](https://docs.pro.coinbase.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | @@ -118,7 +116,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![delta](https://user-images.githubusercontent.com/1294454/99450025-3be60a00-2931-11eb-9302-f4fd8d8589aa.jpg)](https://www.delta.exchange/app/signup/?code=IULYNB) | delta | [Delta Exchange](https://www.delta.exchange/app/signup/?code=IULYNB) | 2 | [API](https://docs.delta.exchange) | | | | [![deribit](https://user-images.githubusercontent.com/1294454/41933112-9e2dd65a-798b-11e8-8440-5bab2959fcb8.jpg)](https://www.deribit.com/reg-1189.4038) | deribit | [Deribit](https://www.deribit.com/reg-1189.4038) | 2 | [API](https://docs.deribit.com/v2) | | | | [![digifinex](https://user-images.githubusercontent.com/51840849/87443315-01283a00-c5fe-11ea-8628-c2a0feaf07ac.jpg)](https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp) | digifinex | [DigiFinex](https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp) | 3 | [API](https://docs.digifinex.com) | | | -| [![dsx](https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg)](https://dsxglobal.com) | dsx | [DSX](https://dsxglobal.com) | 3 | [API](https://dsxglobal.com/developers/publicApi) | | | | [![equos](https://user-images.githubusercontent.com/1294454/107758499-05edd180-6d38-11eb-9e09-0b69602a7a15.jpg)](https://equos.io?referredByCode=zpa8kij4ouvBFup3) | equos | [EQUOS](https://equos.io?referredByCode=zpa8kij4ouvBFup3) | * | [API](https://developer.equos.io) | | | | [![eterbase](https://user-images.githubusercontent.com/1294454/82067900-faeb0f80-96d9-11ea-9f22-0071cfcb9871.jpg)](https://eterbase.exchange/invite/1wjjh4Pe) | eterbase | [Eterbase](https://eterbase.exchange/invite/1wjjh4Pe) | 1 | [API](https://developers.eterbase.exchange) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | | [![exmo](https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg)](https://exmo.me/?ref=131685) | exmo | [EXMO](https://exmo.me/?ref=131685) | 1.1 | [API](https://exmo.me/en/api_doc?ref=131685) | | | @@ -133,10 +130,9 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![gopax](https://user-images.githubusercontent.com/1294454/102897212-ae8a5e00-4478-11eb-9bab-91507c643900.jpg)](https://www.gopax.co.kr) | gopax | [GOPAX](https://www.gopax.co.kr) | 1 | [API](https://gopax.github.io/API/index.en.html) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![hbtc](https://user-images.githubusercontent.com/51840849/80134449-70663300-85a7-11ea-8942-e204cdeaab5d.jpg)](https://www.hbtc.com/register/O2S8NS) | hbtc | [HBTC](https://www.hbtc.com/register/O2S8NS) | 1 | [API](https://github.com/bhexopen/BHEX-OpenApi/tree/master/doc) | | | | [![hitbtc](https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg)](https://hitbtc.com/?ref_id=5a5d39a65d466) | hitbtc | [HitBTC](https://hitbtc.com/?ref_id=5a5d39a65d466) | 2 | [API](https://api.hitbtc.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![hollaex](https://user-images.githubusercontent.com/1294454/75841031-ca375180-5ddd-11ea-8417-b975674c23cb.jpg)](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | hollaex | [HollaEx](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | 1 | [API](https://apidocs.hollaex.com) | | | +| [![hollaex](https://user-images.githubusercontent.com/1294454/75841031-ca375180-5ddd-11ea-8417-b975674c23cb.jpg)](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | hollaex | [HollaEx](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | 2 | [API](https://apidocs.hollaex.com) | | | | [![huobijp](https://user-images.githubusercontent.com/1294454/85734211-85755480-b705-11ea-8b35-0b7f1db33a2f.jpg)](https://www.huobi.co.jp/register/?invite_code=znnq3) | huobijp | [Huobi Japan](https://www.huobi.co.jp/register/?invite_code=znnq3) | 1 | [API](https://api-doc.huobi.co.jp) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![huobipro](https://user-images.githubusercontent.com/1294454/76137448-22748a80-604e-11ea-8069-6e389271911d.jpg)](https://www.huobi.com/en-us/topic/invited/?invite_code=rwrd3) | huobipro | [Huobi Pro](https://www.huobi.com/en-us/topic/invited/?invite_code=rwrd3) | 1 | [API](https://huobiapi.github.io/docs/spot/v1/cn/) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![ice3x](https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg)](https://ice3x.com?ref=14341802) | ice3x | [ICE3X](https://ice3x.com?ref=14341802) | 1 | [API](https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017) | | | | [![idex](https://user-images.githubusercontent.com/51840849/94481303-2f222100-01e0-11eb-97dd-bc14c5943a86.jpg)](https://idex.io) | idex | [IDEX](https://idex.io) | 2 | [API](https://docs.idex.io/) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![independentreserve](https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg)](https://www.independentreserve.com) | independentreserve | [Independent Reserve](https://www.independentreserve.com) | * | [API](https://www.independentreserve.com/API) | | | | [![indodax](https://user-images.githubusercontent.com/51840849/87070508-9358c880-c221-11ea-8dc5-5391afbbb422.jpg)](https://indodax.com/ref/testbitcoincoid/1) | indodax | [INDODAX](https://indodax.com/ref/testbitcoincoid/1) | 2.0 | [API](https://github.com/btcid/indodax-official-api-docs) | | | @@ -172,7 +168,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![tidex](https://user-images.githubusercontent.com/1294454/30781780-03149dc4-a12e-11e7-82bb-313b269d24d4.jpg)](https://tidex.com/exchange/?ref=57f5638d9cd7) | tidex | [Tidex](https://tidex.com/exchange/?ref=57f5638d9cd7) | 3 | [API](https://tidex.com/exchange/public-api) | | | | [![timex](https://user-images.githubusercontent.com/1294454/70423869-6839ab00-1a7f-11ea-8f94-13ae72c31115.jpg)](https://timex.io/?refcode=1x27vNkTbP1uwkCck) | timex | [TimeX](https://timex.io/?refcode=1x27vNkTbP1uwkCck) | 1 | [API](https://docs.timex.io) | | | | [![upbit](https://user-images.githubusercontent.com/1294454/49245610-eeaabe00-f423-11e8-9cba-4b0aed794799.jpg)](https://upbit.com) | upbit | [Upbit](https://upbit.com) | 1 | [API](https://docs.upbit.com/docs/%EC%9A%94%EC%B2%AD-%EC%88%98-%EC%A0%9C%ED%95%9C) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![vaultoro](https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg)](https://www.vaultoro.com) | vaultoro | [Vaultoro](https://www.vaultoro.com) | 1 | [API](https://api.vaultoro.com) | | | | [![vbtc](https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg)](https://vbtc.exchange) | vbtc | [VBTC](https://vbtc.exchange) | 1 | [API](https://blinktrade.com/docs) | | | | [![vcc](https://user-images.githubusercontent.com/1294454/100545356-8427f500-326c-11eb-9539-7d338242d61b.jpg)](https://vcc.exchange?ref=l4xhrH) | vcc | [VCC Exchange](https://vcc.exchange?ref=l4xhrH) | 3 | [API](https://vcc.exchange/api) | | | | [![wavesexchange](https://user-images.githubusercontent.com/1294454/84547058-5fb27d80-ad0b-11ea-8711-78ac8b3c7f31.jpg)](https://waves.exchange) | wavesexchange | [Waves.Exchange](https://waves.exchange) | * | [API](https://docs.waves.exchange) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | @@ -229,13 +224,13 @@ console.log (ccxt.exchanges) // print all available exchanges All-in-one browser bundle (dependencies included), served from a CDN of your choice: -* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@1.42.77/dist/ccxt.browser.js -* unpkg: https://unpkg.com/ccxt@1.42.77/dist/ccxt.browser.js +* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@1.47.49/dist/ccxt.browser.js +* unpkg: https://unpkg.com/ccxt@1.47.49/dist/ccxt.browser.js CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers. ```HTML - + ``` Creates a global `ccxt` object: diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/export-exchanges.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/export-exchanges.js index 580d2cb2c..24ee4806f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/export-exchanges.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/export-exchanges.js @@ -195,7 +195,6 @@ function createMarkdownTable (array, markdownMethod, centeredColumns) { // const columns = underline.split ('|') - for (const i of centeredColumns) { columns[i] = ':' + columns[i].slice (1, columns[i].length - 1) + ':' } @@ -219,51 +218,45 @@ function exportSupportedAndCertifiedExchanges (exchanges, { allExchangesPaths, c const exchangesNotListedInDocs = [ 'hitbtc2' ] const arrayOfExchanges = values (exchanges) + const numExchanges = arrayOfExchanges.length - if (allExchangesPaths) { - + if (allExchangesPaths && numExchanges) { const supportedExchangesMarkdownTable = createMarkdownTable (arrayOfExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , numExchanges = arrayOfExchanges.length , beginning = "The CCXT library currently supports the following " , ending = " cryptocurrency exchange markets and trading APIs:\n\n" , totalString = beginning + numExchanges + ending , allExchangesReplacement = totalString + supportedExchangesMarkdownTable + "$1" , allExchangesRegex = new RegExp ("[^\n]+[\n]{2}\\| logo[^`]+\\|([\n][\n]|[\n]$|$)", 'm') - for (const path of allExchangesPaths) { logExportExchanges (path, allExchangesRegex, allExchangesReplacement) } } - if (proExchangesPaths) { - - const proExchanges = arrayOfExchanges.filter (exchange => exchange.pro) - , proExchangesMarkdownTable = createMarkdownTable (proExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , numExchanges = proExchanges.length + const proExchanges = arrayOfExchanges.filter (exchange => exchange.pro) + const numProExchanges = proExchanges.length + if (proExchangesPaths && numProExchanges) { + const proExchangesMarkdownTable = createMarkdownTable (proExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) , beginning = "The CCXT Pro library currently supports the following " , ending = " cryptocurrency exchange markets and WebSocket trading APIs:\n\n" - , totalString = beginning + numExchanges + ending + , totalString = beginning + numProExchanges + ending , proExchangesReplacement = totalString + proExchangesMarkdownTable + "$1" , proExchangesRegex = new RegExp ("[^\n]+[\n]{2}\\|[^`]+\\|([\n][\n]|[\n]$|$)", 'm') - for (const path of proExchangesPaths) { logExportExchanges (path, proExchangesRegex, proExchangesReplacement) } } - if (certifiedExchangesPaths) { - const certifiedExchanges = arrayOfExchanges.filter (exchange => exchange.certified) - , certifiedExchangesMarkdownTable = createMarkdownTable (certifiedExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , certifiedExchangesReplacement = '$1' + certifiedExchangesMarkdownTable + "\n" - , certifiedExchangesRegex = new RegExp ("^(## Certified Cryptocurrency Exchanges\n{3})(?:\\|.+\\|$\n)+", 'm') - + const certifiedExchanges = arrayOfExchanges.filter (exchange => exchange.certified) + if (certifiedExchangesPaths && certifiedExchanges.length) { + const certifiedExchangesMarkdownTable = createMarkdownTable (certifiedExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) + , certifiedExchangesReplacement = '$1' + certifiedExchangesMarkdownTable + "\n" + , certifiedExchangesRegex = new RegExp ("^(## Certified Cryptocurrency Exchanges\n{3})(?:\\|.+\\|$\n)+", 'm') for (const path of certifiedExchangesPaths) { logExportExchanges (path, certifiedExchangesRegex, certifiedExchangesReplacement) } } if (exchangesByCountriesPaths) { - const exchangesByCountriesMarkdownTable = createMarkdownTable (arrayOfExchanges, createMarkdownListOfExchangesByCountries, [ 4, 5 ]) const result = "# Exchanges By Country\n\nThe ccxt library currently supports the following cryptocurrency exchange markets and trading APIs:\n\n" + exchangesByCountriesMarkdownTable + "\n\n" for (const path of exchangesByCountriesPaths) { @@ -385,7 +378,7 @@ function exportEverything () { replacement: "exchanges = [\n" + " '" + ids.join ("',\n '") + "'," + "\n]", }, { - file: './php/base/Exchange.php', + file: './php/Exchange.php', regex: /public static \$exchanges \= array\s*\([^\)]+\)/, replacement: "public static $exchanges = array(\n '" + ids.join ("',\n '") + "',\n )", }, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/transpile.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/transpile.js index 948a34c0f..233d15e6c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/transpile.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/build/transpile.js @@ -34,6 +34,7 @@ class Transpiler { [ /\.safeIntegerProduct2\s/g, '.safe_integer_product_2'], [ /\.safeTimestamp2\s/g, '.safe_timestamp_2'], [ /\.safeString2\s/g, '.safe_string_2'], + [ /\.safeNumber2\s/g, '.safe_number_2'], [ /\.safeStringLower2\s/g, '.safe_string_lower_2'], [ /\.safeStringUpper2\s/g, '.safe_string_upper_2'], [ /\.safeValue2\s/g, '.safe_value_2'], @@ -195,6 +196,10 @@ class Transpiler { [ /Number\.MAX_SAFE_INTEGER/g, 'float(\'inf\')'], [ /function\s*(\w+\s*\([^)]+\))\s*{/g, 'def $1:'], [ /assert\s*\((.+)\);/g, 'assert $1'], + [ /Precise\.stringAdd\s/g, 'Precise.string_add' ], + [ /Precise\.stringMul\s/g, 'Precise.string_mul' ], + [ /Precise\.stringDiv\s/g, 'Precise.string_div' ], + [ /Precise\.stringSub\s/g, 'Precise.string_sub' ], // insert common regexes in the middle (critical) ].concat (this.getCommonRegexes ()).concat ([ @@ -227,7 +232,7 @@ class Transpiler { [ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(?:\<=|\>=|<|>)\s*(.*)\s*\;[^\)]+\)\s*{/g, 'for $1 in range($2, $3):'], [ /\s\|\|\s/g, ' or ' ], [ /\s\&\&\s/g, ' and ' ], - [ /\!([^\='"])/g, 'not $1'], + [ /\!([^\s\='"])/g, 'not $1'], [ /\.push\s*\(([\s\S]+?)\);/g, '.append($1);' ], [ /^(\s*}\s*$)+/gm, '' ], [ /\;(\s+?\/\/.+?)/g, '$1' ], @@ -243,9 +248,6 @@ class Transpiler { [ /parseFloat\s*/g, 'float'], [ /parseInt\s*/g, 'int'], [ /self\[([^\]+]+)\]/g, 'getattr(self, $1)' ], - [ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], - [ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], - [ /([^\s(:]+)\.length/g, 'len($1)' ], [ /Math\.floor\s*\(([^\)]+)\)/g, 'int(math.floor($1))' ], [ /Math\.abs\s*\(([^\)]+)\)/g, 'abs($1)' ], [ /Math\.pow\s*\(([^\)]+)\)/g, 'math.pow($1)' ], @@ -253,6 +255,9 @@ class Transpiler { [ /Math\.ceil\s*\(([^\)]+)\)/g, 'int(math.ceil($1))' ], [ /Math\.log/g, 'math.log' ], [ /([a-zA-Z0-9_\.]*\([^\)]+\)|[^\s]+)\s+\?\s*([^\:]+)\s+\:\s*([^\n]+)/g, '$2 if $1 else $3'], + [ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], + [ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], + [ /([^\s(:]+)\.length/g, 'len($1)' ], [ /(^|\s)\/\//g, '$1#' ], [ /([^\n\s]) #/g, '$1 #' ], // PEP8 E261 [ /\.indexOf/g, '.find'], @@ -336,6 +341,10 @@ class Transpiler { [ /(\w+)\.shift\s*\(\)/g, 'array_shift($1)' ], [ /(\w+)\.pop\s*\(\)/g, 'array_pop($1)' ], [ /Number\.MAX_SAFE_INTEGER/g, 'PHP_INT_MAX' ], + [ /Precise\.stringAdd\s/g, 'Precise::string_add' ], + [ /Precise\.stringDiv\s/g, 'Precise::string_div' ], + [ /Precise\.stringMul\s/g, 'Precise::string_mul' ], + [ /Precise\.stringSub\s/g, 'Precise::string_sub' ], // insert common regexes in the middle (critical) ].concat (this.getCommonRegexes ()).concat ([ @@ -404,6 +413,7 @@ class Transpiler { [ /([^\(\s]+)\s+%\s+([^\s\,\;\)]+)/g, 'fmod($1, $2)' ], [ /\(([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0\)/g, '(mb_strpos($1, $2) !== false)' ], [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0/g, 'mb_strpos($1, $2) !== false' ], + [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\<\s*0/g, 'mb_strpos($1, $2) === false' ], [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)/g, 'mb_strpos($1, $2)' ], [ /\(([^\s\(]+)\sin\s([^\)]+)\)/g, '(is_array($2) && array_key_exists($1, $2))' ], [ /([^\s]+)\.join\s*\(\s*([^\)]+?)\s*\)/g, 'implode($2, $1)' ], @@ -578,6 +588,9 @@ class Transpiler { precisionImports.push ('from ccxt.base.decimal_to_precision import ' + constant) } } + if (bodyAsString.match (/[\s(]Precise/)) { + precisionImports.push ('from ccxt.base.precise import Precise') + } header = header.concat (libraries, errorImports, precisionImports) @@ -633,7 +646,13 @@ class Transpiler { } } - header = header.concat (errorImports) + const precisionImports = [] + + if (async && bodyAsString.match (/[\s(]Precise/)) { + precisionImports.push ('use \\ccxt\\Precise;') + } + + header = header.concat (errorImports).concat (precisionImports) methods = methods.concat (this.getPHPBaseMethods ()) @@ -1179,7 +1198,7 @@ class Transpiler { function phpMakeErrorClassFile (name, parent) { const useClause = "\nuse " + parent + ";\n" - const requireClause = "\nrequire_once PATH_TO_CCXT_BASE . '" + parent + ".php';\n" + const requireClause = "\nrequire_once PATH_TO_CCXT . '" + parent + ".php';\n" const phpBody = [ '; - createLimitOrder (symbol: string, side: Order['side'], amount: number, price?: number, params?: Params): Promise; + createLimitOrder (symbol: string, side: Order['side'], amount: number, price: number, params?: Params): Promise; + createLimitBuyOrder (symbol: string, amount: number, price: number, params?: Params): Promise; + createLimitSellOrder (symbol: string, amount: number, price: number, params?: Params): Promise; createMarketOrder (symbol: string, side: Order['side'], amount: number, price?: number, params?: Params): Promise; createOrder (symbol: string, type: Order['type'], side: Order['side'], amount: number, price?: number, params?: Params): Promise; decode (str: string): string; @@ -423,8 +425,8 @@ declare module 'ccxt' { /* tslint:disable */ export class aax extends Exchange {} - export class acx extends Exchange {} export class aofex extends Exchange {} + export class ascendex extends Exchange {} export class bequant extends hitbtc {} export class bibox extends Exchange {} export class bigone extends Exchange {} @@ -442,7 +444,6 @@ declare module 'ccxt' { export class bithumb extends Exchange {} export class bitkk extends zb {} export class bitmart extends Exchange {} - export class bitmax extends Exchange {} export class bitmex extends Exchange {} export class bitpanda extends Exchange {} export class bitso extends Exchange {} @@ -465,7 +466,6 @@ declare module 'ccxt' { export class bytetrade extends Exchange {} export class cdax extends huobipro {} export class cex extends Exchange {} - export class chilebit extends foxbit {} export class coinbase extends Exchange {} export class coinbaseprime extends coinbasepro {} export class coinbasepro extends Exchange {} @@ -484,7 +484,6 @@ declare module 'ccxt' { export class delta extends Exchange {} export class deribit extends Exchange {} export class digifinex extends Exchange {} - export class dsx extends Exchange {} export class equos extends Exchange {} export class eterbase extends Exchange {} export class exmo extends Exchange {} @@ -502,14 +501,13 @@ declare module 'ccxt' { export class hollaex extends Exchange {} export class huobijp extends huobipro {} export class huobipro extends Exchange {} - export class ice3x extends Exchange {} export class idex extends Exchange {} export class independentreserve extends Exchange {} export class indodax extends Exchange {} export class itbit extends Exchange {} export class kraken extends Exchange {} export class kucoin extends Exchange {} - export class kuna extends acx {} + export class kuna extends Exchange {} export class lakebtc extends Exchange {} export class latoken extends Exchange {} export class lbank extends Exchange {} @@ -538,7 +536,6 @@ declare module 'ccxt' { export class tidex extends Exchange {} export class timex extends Exchange {} export class upbit extends Exchange {} - export class vaultoro extends Exchange {} export class vbtc extends foxbit {} export class vcc extends Exchange {} export class wavesexchange extends Exchange {} @@ -553,8 +550,8 @@ declare module 'ccxt' { export type ExchangeId = | 'aax' - | 'acx' | 'aofex' + | 'ascendex' | 'bequant' | 'bibox' | 'bigone' @@ -572,7 +569,6 @@ declare module 'ccxt' { | 'bithumb' | 'bitkk' | 'bitmart' - | 'bitmax' | 'bitmex' | 'bitpanda' | 'bitso' @@ -595,7 +591,6 @@ declare module 'ccxt' { | 'bytetrade' | 'cdax' | 'cex' - | 'chilebit' | 'coinbase' | 'coinbaseprime' | 'coinbasepro' @@ -614,7 +609,6 @@ declare module 'ccxt' { | 'delta' | 'deribit' | 'digifinex' - | 'dsx' | 'equos' | 'eterbase' | 'exmo' @@ -632,7 +626,6 @@ declare module 'ccxt' { | 'hollaex' | 'huobijp' | 'huobipro' - | 'ice3x' | 'idex' | 'independentreserve' | 'indodax' @@ -668,7 +661,6 @@ declare module 'ccxt' { | 'tidex' | 'timex' | 'upbit' - | 'vaultoro' | 'vbtc' | 'vcc' | 'wavesexchange' diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/ccxt.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/ccxt.js index 1d5c72642..27dc35101 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/ccxt.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/ccxt.js @@ -35,7 +35,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.42.77' +const version = '1.47.49' Exchange.ccxtVersion = version @@ -43,8 +43,8 @@ Exchange.ccxtVersion = version const exchanges = { 'aax': require ('./js/aax.js'), - 'acx': require ('./js/acx.js'), 'aofex': require ('./js/aofex.js'), + 'ascendex': require ('./js/ascendex.js'), 'bequant': require ('./js/bequant.js'), 'bibox': require ('./js/bibox.js'), 'bigone': require ('./js/bigone.js'), @@ -62,7 +62,6 @@ const exchanges = { 'bithumb': require ('./js/bithumb.js'), 'bitkk': require ('./js/bitkk.js'), 'bitmart': require ('./js/bitmart.js'), - 'bitmax': require ('./js/bitmax.js'), 'bitmex': require ('./js/bitmex.js'), 'bitpanda': require ('./js/bitpanda.js'), 'bitso': require ('./js/bitso.js'), @@ -85,7 +84,6 @@ const exchanges = { 'bytetrade': require ('./js/bytetrade.js'), 'cdax': require ('./js/cdax.js'), 'cex': require ('./js/cex.js'), - 'chilebit': require ('./js/chilebit.js'), 'coinbase': require ('./js/coinbase.js'), 'coinbaseprime': require ('./js/coinbaseprime.js'), 'coinbasepro': require ('./js/coinbasepro.js'), @@ -104,7 +102,6 @@ const exchanges = { 'delta': require ('./js/delta.js'), 'deribit': require ('./js/deribit.js'), 'digifinex': require ('./js/digifinex.js'), - 'dsx': require ('./js/dsx.js'), 'equos': require ('./js/equos.js'), 'eterbase': require ('./js/eterbase.js'), 'exmo': require ('./js/exmo.js'), @@ -122,7 +119,6 @@ const exchanges = { 'hollaex': require ('./js/hollaex.js'), 'huobijp': require ('./js/huobijp.js'), 'huobipro': require ('./js/huobipro.js'), - 'ice3x': require ('./js/ice3x.js'), 'idex': require ('./js/idex.js'), 'independentreserve': require ('./js/independentreserve.js'), 'indodax': require ('./js/indodax.js'), @@ -158,7 +154,6 @@ const exchanges = { 'tidex': require ('./js/tidex.js'), 'timex': require ('./js/timex.js'), 'upbit': require ('./js/upbit.js'), - 'vaultoro': require ('./js/vaultoro.js'), 'vbtc': require ('./js/vbtc.js'), 'vcc': require ('./js/vcc.js'), 'wavesexchange': require ('./js/wavesexchange.js'), diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/dist/ccxt.browser.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/dist/ccxt.browser.js index e8b439fb1..334681baa 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/dist/ccxt.browser.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/dist/ccxt.browser.js @@ -43,7 +43,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.42.77' +const version = '1.47.49' Exchange.ccxtVersion = version @@ -51,8 +51,8 @@ Exchange.ccxtVersion = version const exchanges = { 'aax': require ('./js/aax.js'), - 'acx': require ('./js/acx.js'), 'aofex': require ('./js/aofex.js'), + 'ascendex': require ('./js/ascendex.js'), 'bequant': require ('./js/bequant.js'), 'bibox': require ('./js/bibox.js'), 'bigone': require ('./js/bigone.js'), @@ -70,7 +70,6 @@ const exchanges = { 'bithumb': require ('./js/bithumb.js'), 'bitkk': require ('./js/bitkk.js'), 'bitmart': require ('./js/bitmart.js'), - 'bitmax': require ('./js/bitmax.js'), 'bitmex': require ('./js/bitmex.js'), 'bitpanda': require ('./js/bitpanda.js'), 'bitso': require ('./js/bitso.js'), @@ -93,7 +92,6 @@ const exchanges = { 'bytetrade': require ('./js/bytetrade.js'), 'cdax': require ('./js/cdax.js'), 'cex': require ('./js/cex.js'), - 'chilebit': require ('./js/chilebit.js'), 'coinbase': require ('./js/coinbase.js'), 'coinbaseprime': require ('./js/coinbaseprime.js'), 'coinbasepro': require ('./js/coinbasepro.js'), @@ -112,7 +110,6 @@ const exchanges = { 'delta': require ('./js/delta.js'), 'deribit': require ('./js/deribit.js'), 'digifinex': require ('./js/digifinex.js'), - 'dsx': require ('./js/dsx.js'), 'equos': require ('./js/equos.js'), 'eterbase': require ('./js/eterbase.js'), 'exmo': require ('./js/exmo.js'), @@ -130,7 +127,6 @@ const exchanges = { 'hollaex': require ('./js/hollaex.js'), 'huobijp': require ('./js/huobijp.js'), 'huobipro': require ('./js/huobipro.js'), - 'ice3x': require ('./js/ice3x.js'), 'idex': require ('./js/idex.js'), 'independentreserve': require ('./js/independentreserve.js'), 'indodax': require ('./js/indodax.js'), @@ -166,7 +162,6 @@ const exchanges = { 'tidex': require ('./js/tidex.js'), 'timex': require ('./js/timex.js'), 'upbit': require ('./js/upbit.js'), - 'vaultoro': require ('./js/vaultoro.js'), 'vbtc': require ('./js/vbtc.js'), 'vcc': require ('./js/vcc.js'), 'wavesexchange': require ('./js/wavesexchange.js'), @@ -184,7 +179,7 @@ module.exports = Object.assign ({ version, Exchange, 'exchanges': Object.keys (e //----------------------------------------------------------------------------- -},{"./js/aax.js":3,"./js/acx.js":4,"./js/aofex.js":5,"./js/base/Exchange":6,"./js/base/errors":8,"./js/base/functions":9,"./js/bequant.js":20,"./js/bibox.js":21,"./js/bigone.js":22,"./js/binance.js":23,"./js/binanceus.js":24,"./js/bit2c.js":25,"./js/bitbank.js":26,"./js/bitbay.js":27,"./js/bitcoincom.js":28,"./js/bitfinex.js":29,"./js/bitfinex2.js":30,"./js/bitflyer.js":31,"./js/bitforex.js":32,"./js/bitget.js":33,"./js/bithumb.js":34,"./js/bitkk.js":35,"./js/bitmart.js":36,"./js/bitmax.js":37,"./js/bitmex.js":38,"./js/bitpanda.js":39,"./js/bitso.js":40,"./js/bitstamp.js":41,"./js/bitstamp1.js":42,"./js/bittrex.js":43,"./js/bitvavo.js":44,"./js/bitz.js":45,"./js/bl3p.js":46,"./js/bleutrade.js":47,"./js/braziliex.js":48,"./js/btcalpha.js":49,"./js/btcbox.js":50,"./js/btcmarkets.js":51,"./js/btctradeua.js":52,"./js/btcturk.js":53,"./js/buda.js":54,"./js/bw.js":55,"./js/bybit.js":56,"./js/bytetrade.js":57,"./js/cdax.js":58,"./js/cex.js":59,"./js/chilebit.js":60,"./js/coinbase.js":61,"./js/coinbaseprime.js":62,"./js/coinbasepro.js":63,"./js/coincheck.js":64,"./js/coinegg.js":65,"./js/coinex.js":66,"./js/coinfalcon.js":67,"./js/coinfloor.js":68,"./js/coingi.js":69,"./js/coinmarketcap.js":70,"./js/coinmate.js":71,"./js/coinone.js":72,"./js/coinspot.js":73,"./js/crex24.js":74,"./js/currencycom.js":75,"./js/delta.js":76,"./js/deribit.js":77,"./js/digifinex.js":78,"./js/dsx.js":79,"./js/equos.js":80,"./js/eterbase.js":81,"./js/exmo.js":82,"./js/exx.js":83,"./js/fcoin.js":84,"./js/fcoinjp.js":85,"./js/flowbtc.js":86,"./js/foxbit.js":87,"./js/ftx.js":88,"./js/gateio.js":89,"./js/gemini.js":90,"./js/gopax.js":91,"./js/hbtc.js":92,"./js/hitbtc.js":93,"./js/hollaex.js":94,"./js/huobijp.js":95,"./js/huobipro.js":96,"./js/ice3x.js":97,"./js/idex.js":98,"./js/independentreserve.js":99,"./js/indodax.js":100,"./js/itbit.js":101,"./js/kraken.js":102,"./js/kucoin.js":103,"./js/kuna.js":104,"./js/lakebtc.js":105,"./js/latoken.js":106,"./js/lbank.js":107,"./js/liquid.js":108,"./js/luno.js":109,"./js/lykke.js":110,"./js/mercado.js":111,"./js/mixcoins.js":112,"./js/ndax.js":113,"./js/novadax.js":114,"./js/oceanex.js":115,"./js/okcoin.js":116,"./js/okex.js":117,"./js/paymium.js":118,"./js/phemex.js":119,"./js/poloniex.js":120,"./js/probit.js":121,"./js/qtrade.js":122,"./js/rightbtc.js":123,"./js/ripio.js":124,"./js/southxchange.js":125,"./js/stex.js":166,"./js/surbitcoin.js":167,"./js/therock.js":168,"./js/tidebit.js":169,"./js/tidex.js":170,"./js/timex.js":171,"./js/upbit.js":172,"./js/vaultoro.js":173,"./js/vbtc.js":174,"./js/vcc.js":175,"./js/wavesexchange.js":176,"./js/whitebit.js":177,"./js/xbtce.js":178,"./js/xena.js":179,"./js/yobit.js":180,"./js/zaif.js":181,"./js/zb.js":182}],3:[function(require,module,exports){ +},{"./js/aax.js":3,"./js/aofex.js":4,"./js/ascendex.js":5,"./js/base/Exchange":6,"./js/base/errors":9,"./js/base/functions":10,"./js/bequant.js":21,"./js/bibox.js":22,"./js/bigone.js":23,"./js/binance.js":24,"./js/binanceus.js":25,"./js/bit2c.js":26,"./js/bitbank.js":27,"./js/bitbay.js":28,"./js/bitcoincom.js":29,"./js/bitfinex.js":30,"./js/bitfinex2.js":31,"./js/bitflyer.js":32,"./js/bitforex.js":33,"./js/bitget.js":34,"./js/bithumb.js":35,"./js/bitkk.js":36,"./js/bitmart.js":37,"./js/bitmex.js":38,"./js/bitpanda.js":39,"./js/bitso.js":40,"./js/bitstamp.js":41,"./js/bitstamp1.js":42,"./js/bittrex.js":43,"./js/bitvavo.js":44,"./js/bitz.js":45,"./js/bl3p.js":46,"./js/bleutrade.js":47,"./js/braziliex.js":48,"./js/btcalpha.js":49,"./js/btcbox.js":50,"./js/btcmarkets.js":51,"./js/btctradeua.js":52,"./js/btcturk.js":53,"./js/buda.js":54,"./js/bw.js":55,"./js/bybit.js":56,"./js/bytetrade.js":57,"./js/cdax.js":58,"./js/cex.js":59,"./js/coinbase.js":60,"./js/coinbaseprime.js":61,"./js/coinbasepro.js":62,"./js/coincheck.js":63,"./js/coinegg.js":64,"./js/coinex.js":65,"./js/coinfalcon.js":66,"./js/coinfloor.js":67,"./js/coingi.js":68,"./js/coinmarketcap.js":69,"./js/coinmate.js":70,"./js/coinone.js":71,"./js/coinspot.js":72,"./js/crex24.js":73,"./js/currencycom.js":74,"./js/delta.js":75,"./js/deribit.js":76,"./js/digifinex.js":77,"./js/equos.js":78,"./js/eterbase.js":79,"./js/exmo.js":80,"./js/exx.js":81,"./js/fcoin.js":82,"./js/fcoinjp.js":83,"./js/flowbtc.js":84,"./js/foxbit.js":85,"./js/ftx.js":86,"./js/gateio.js":87,"./js/gemini.js":88,"./js/gopax.js":89,"./js/hbtc.js":90,"./js/hitbtc.js":91,"./js/hollaex.js":92,"./js/huobijp.js":93,"./js/huobipro.js":94,"./js/idex.js":95,"./js/independentreserve.js":96,"./js/indodax.js":97,"./js/itbit.js":98,"./js/kraken.js":99,"./js/kucoin.js":100,"./js/kuna.js":101,"./js/lakebtc.js":102,"./js/latoken.js":103,"./js/lbank.js":104,"./js/liquid.js":105,"./js/luno.js":106,"./js/lykke.js":107,"./js/mercado.js":108,"./js/mixcoins.js":109,"./js/ndax.js":110,"./js/novadax.js":111,"./js/oceanex.js":112,"./js/okcoin.js":113,"./js/okex.js":114,"./js/paymium.js":115,"./js/phemex.js":116,"./js/poloniex.js":117,"./js/probit.js":118,"./js/qtrade.js":119,"./js/rightbtc.js":120,"./js/ripio.js":121,"./js/southxchange.js":122,"./js/stex.js":163,"./js/surbitcoin.js":164,"./js/therock.js":165,"./js/tidebit.js":166,"./js/tidex.js":167,"./js/timex.js":168,"./js/upbit.js":169,"./js/vbtc.js":170,"./js/vcc.js":171,"./js/wavesexchange.js":172,"./js/whitebit.js":173,"./js/xbtce.js":174,"./js/xena.js":175,"./js/yobit.js":176,"./js/zaif.js":177,"./js/zb.js":178}],3:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -192,6 +187,7 @@ module.exports = Object.assign ({ version, Exchange, 'exchanges': Object.keys (e const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, ExchangeNotAvailable, OrderNotFound, InvalidOrder, CancelPending, RateLimitExceeded, InsufficientFunds, BadRequest, BadSymbol, PermissionDenied } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -222,6 +218,7 @@ module.exports = class aax extends Exchange { 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, + 'fetchStatus': true, 'fetchTicker': 'emulated', 'fetchTickers': true, 'fetchTrades': true, @@ -420,6 +417,37 @@ module.exports = class aax extends Exchange { }); } + async fetchStatus (params = {}) { + const response = await this.publicGetAnnouncementMaintenance (params); + // + // { + // "code": 1, + // "data": { + // "startTime":"2020-06-25T02:15:00.000Z", + // "endTime":"2020-06-25T02:45:00.000Z", + // "description":"Spot Trading :UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45),Futures Trading: UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45).We apologize for any inconvenience caused. Thank you for your patience and understanding.Should you have any enquiries, please do not hesitate our live chat support or via email at cs@aax.com." + // }, + // "message":"success", + // "ts":1593043237000 + // } + // + const data = this.safeValue (response, 'data', {}); + const timestamp = this.milliseconds (); + const startTime = this.parse8601 (this.safeString (data, 'startTime')); + const endTime = this.parse8601 (this.safeString (data, 'endTime')); + const update = { + 'updated': this.safeInteger (response, 'ts', timestamp), + }; + if (endTime !== undefined) { + const startTimeIsOk = (startTime === undefined) ? true : (timestamp < startTime); + const isOk = (timestamp > endTime) || startTimeIsOk; + update['eta'] = endTime; + update['status'] = isOk ? 'ok' : 'maintenance'; + } + this.status = this.extend (this.status, update); + return this.status; + } + async fetchMarkets (params = {}) { const response = await this.publicGetInstruments (params); // @@ -505,8 +533,8 @@ module.exports = class aax extends Exchange { const quote = this.safeCurrencyCode (quoteId); const status = this.safeString (market, 'status'); const active = (status === 'enable'); - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); const type = this.safeString (market, 'type'); let inverse = undefined; let linear = undefined; @@ -524,8 +552,8 @@ module.exports = class aax extends Exchange { symbol = base + '/' + quote; } const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; result.push ({ 'id': id, @@ -583,8 +611,8 @@ module.exports = class aax extends Exchange { const timestamp = this.safeInteger (ticker, 't'); const marketId = this.safeString (ticker, 's'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'c'); - const open = this.safeFloat (ticker, 'o'); + const last = this.safeNumber (ticker, 'c'); + const open = this.safeNumber (ticker, 'o'); let change = undefined; let percentage = undefined; let average = undefined; @@ -595,13 +623,13 @@ module.exports = class aax extends Exchange { } average = this.sum (last, open) / 2; } - const quoteVolume = this.safeFloat (ticker, 'v'); + const quoteVolume = this.safeNumber (ticker, 'v'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'h'), - 'low': this.safeFloat (ticker, 'l'), + 'high': this.safeNumber (ticker, 'h'), + 'low': this.safeNumber (ticker, 'l'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -748,8 +776,8 @@ module.exports = class aax extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let price = this.safeFloat2 (trade, 'p', 'filledPrice'); - const amount = this.safeFloat2 (trade, 'q', 'filledQty'); + let priceString = this.safeString2 (trade, 'p', 'filledPrice'); + const amountString = this.safeString2 (trade, 'q', 'filledQty'); const orderId = this.safeString (trade, 'orderID'); const isTaker = this.safeValue (trade, 'taker'); let takerOrMaker = undefined; @@ -763,17 +791,15 @@ module.exports = class aax extends Exchange { side = 'sell'; } if (side === undefined) { - side = (price > 0) ? 'buy' : 'sell'; - } - side = (price > 0) ? 'buy' : 'sell'; - price = Math.abs (price); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; + side = (priceString[0] === '-') ? 'sell' : 'buy'; } + priceString = (priceString[0] === '-') ? priceString.slice (1) : priceString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderType = this.parseOrderType (this.safeString (trade, 'orderType')); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -841,11 +867,11 @@ module.exports = class aax extends Exchange { // return [ this.safeTimestamp (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -930,12 +956,12 @@ module.exports = class aax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'unavailable'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'unavailable'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -963,7 +989,7 @@ module.exports = class aax extends Exchange { request['clOrdID'] = clientOrderId; params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { if ((orderType === 'STOP-LIMIT') || (orderType === 'STOP')) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders'); @@ -1081,7 +1107,7 @@ module.exports = class aax extends Exchange { // 'price': this.priceToPrecision (symbol, price), // 'stopPrice': this.priceToPrecision (symbol, stopPrice), }; - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1718,15 +1744,18 @@ module.exports = class aax extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const price = this.safeFloat (order, 'price'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const price = this.safeNumber (order, 'price'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'Post-Only'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeString (order, 'leavesQty'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + let remaining = this.safeNumber (order, 'leavesQty'); + if ((filled === 0) && (remaining === 0)) { + remaining = undefined; + } let cost = undefined; let lastTradeTimestamp = undefined; if (filled !== undefined) { @@ -1741,7 +1770,7 @@ module.exports = class aax extends Exchange { } } let fee = undefined; - const feeCost = this.safeFloat (order, 'commission'); + const feeCost = this.safeNumber (order, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -1970,496 +1999,7 @@ module.exports = class aax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],4:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { InsufficientFunds, OrderNotFound } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class acx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'acx', - 'name': 'ACX', - 'countries': [ 'AU' ], - 'rateLimit': 1000, - 'version': 'v2', - 'has': { - 'cancelOrder': true, - 'CORS': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchMarkets': true, - 'fetchOHLCV': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTime': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '12h': '720', - '1d': '1440', - '3d': '4320', - '1w': '10080', - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg', - 'extension': '.json', - 'api': 'https://acx.io/api', - 'www': 'https://acx.io', - 'doc': 'https://acx.io/documents/api_v2', - }, - 'api': { - 'public': { - 'get': [ - 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. - 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator - 'k', // Get OHLC(k line) of specific market - 'markets', // Get all available markets - 'order_book', // Get the order book of specified market - 'order_book/{market}', - 'tickers', // Get ticker of all markets - 'tickers/{market}', // Get ticker of specific market - 'timestamp', // Get server current time, in seconds since Unix epoch - 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. - 'trades/{market}', - ], - }, - 'private': { - 'get': [ - 'members/me', // Get your profile and accounts info - 'deposits', // Get your deposits history - 'deposit', // Get details of specific deposit - 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. - 'orders', // Get your orders, results is paginated - 'order', // Get information of specified order - 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. - 'withdraws', // Get your cryptocurrency withdraws - 'withdraw', // Get your cryptocurrency withdraw - ], - 'post': [ - 'orders', // Create a Sell/Buy order - 'orders/multi', // Create multiple sell/buy orders - 'orders/clear', // Cancel all my orders - 'order/delete', // Cancel an order - 'withdraw', // Create a withdraw - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': false, - 'percentage': true, - 'maker': 0.2 / 100, - 'taker': 0.2 / 100, - }, - 'funding': { - 'tierBased': false, - 'percentage': true, - 'withdraw': {}, // There is only 1% fee on withdrawals to your bank account. - }, - }, - 'commonCurrencies': { - 'PLA': 'Plair', - }, - 'exceptions': { - '2002': InsufficientFunds, - '2003': OrderNotFound, - }, - }); - } - - async fetchMarkets (params = {}) { - const markets = await this.publicGetMarkets (params); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = market['id']; - const symbol = market['name']; - let baseId = this.safeString (market, 'base_unit'); - let quoteId = this.safeString (market, 'quote_unit'); - if ((baseId === undefined) || (quoteId === undefined)) { - const ids = symbol.split ('/'); - baseId = ids[0].toLowerCase (); - quoteId = ids[1].toLowerCase (); - } - let base = baseId.toUpperCase (); - let quote = quoteId.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - // todo: find out their undocumented precision and limits - const precision = { - 'amount': 8, - 'price': 8, - }; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'precision': precision, - 'info': market, - 'active': undefined, - 'limits': this.limits, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetMembersMe (params); - const balances = this.safeValue (response, 'accounts'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 300 - } - const orderbook = await this.publicGetDepth (this.extend (request, params)); - const timestamp = this.safeTimestamp (orderbook, 'timestamp'); - return this.parseOrderBook (orderbook, timestamp); - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.safeTimestamp (ticker, 'at'); - ticker = ticker['ticker']; - let symbol = undefined; - if (market) { - symbol = market['symbol']; - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetTickers (params); - const ids = Object.keys (response); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let market = undefined; - let symbol = id; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } else { - let base = id.slice (0, 3); - let quote = id.slice (3, 6); - base = base.toUpperCase (); - quote = quote.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - symbol = base + '/' + quote; - } - result[symbol] = this.parseTicker (response[id], market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTickersMarket (this.extend (request, params)); - return this.parseTicker (response, market); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const id = this.safeString (trade, 'tid'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': undefined, - 'side': undefined, - 'order': undefined, - 'takerOrMaker': undefined, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), - 'cost': this.safeFloat (trade, 'funds'), - 'fee': undefined, - }; - } - - async fetchTime (params = {}) { - const response = await this.publicGetTimestamp (params); - // - // 1594911427 - // - return response * 1000; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - return [ - this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (limit === undefined) { - limit = 500; // default is 30 - } - const request = { - 'market': market['id'], - 'period': this.timeframes[timeframe], - 'limit': limit, - }; - if (since !== undefined) { - request['timestamp'] = parseInt (since / 1000); - } - const response = await this.publicGetK (this.extend (request, params)); - return this.parseOHLCVs (response, market, timeframe, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'done': 'closed', - 'wait': 'open', - 'cancel': 'canceled', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - const marketId = this.safeString (order, 'market'); - const symbol = this.safeSymbol (marketId, market); - const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const status = this.parseOrderStatus (this.safeString (order, 'state')); - const type = this.safeString (order, 'type'); - const side = this.safeString (order, 'side'); - const id = this.safeString (order, 'id'); - return { - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': this.safeFloat (order, 'price'), - 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'volume'), - 'filled': this.safeFloat (order, 'executed_volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'trades': undefined, - 'fee': undefined, - 'info': order, - 'cost': undefined, - 'average': undefined, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': parseInt (id), - }; - const response = await this.privateGetOrder (this.extend (request, params)); - return this.parseOrder (response); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'market': this.marketId (symbol), - 'side': side, - 'volume': amount.toString (), - 'ord_type': type, - }; - if (type === 'limit') { - request['price'] = price.toString (); - } - const response = await this.privatePostOrders (this.extend (request, params)); - const marketId = this.safeValue (response, 'market'); - const market = this.safeValue (this.markets_by_id, marketId); - return this.parseOrder (response, market); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - const response = await this.privatePostOrderDelete (this.extend (request, params)); - const order = this.parseOrder (response); - const status = order['status']; - if (status === 'closed' || status === 'canceled') { - throw new OrderNotFound (this.id + ' ' + this.json (order)); - } - return order; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - // they have XRP but no docs on memo/tag - const request = { - 'currency': currency['id'], - 'sum': amount, - 'address': address, - }; - const response = await this.privatePostWithdraw (this.extend (request, params)); - // withdrawal response is undocumented - return { - 'info': response, - 'id': undefined, - }; - } - - nonce () { - return this.milliseconds (); - } - - encodeParams (params) { - if ('orders' in params) { - const orders = params['orders']; - let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); - for (let i = 0; i < orders.length; i++) { - const order = orders[i]; - const keys = Object.keys (order); - for (let k = 0; k < keys.length; k++) { - const key = keys[k]; - const value = order[key]; - query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); - } - } - return query; - } - return this.urlencode (this.keysort (params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let request = '/api/' + this.version + '/' + this.implodeParams (path, params); - if ('extension' in this.urls) { - request += this.urls['extension']; - } - const query = this.omit (params, this.extractParams (path)); - let url = this.urls['api'] + request; - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce ().toString (); - const query = this.encodeParams (this.extend ({ - 'access_key': this.apiKey, - 'tonce': nonce, - }, params)); - const auth = method + '|' + request + '|' + query; - const signed = this.hmac (this.encode (auth), this.encode (this.secret)); - const suffix = query + '&signature=' + signed; - if (method === 'GET') { - url += '?' + suffix; - } else { - body = suffix; - headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; - } - if (code === 400) { - const error = this.safeValue (response, 'error'); - const errorCode = this.safeString (error, 'code'); - const feedback = this.id + ' ' + this.json (response); - this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); - // fallback to default error handler - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],5:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],4:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -2467,6 +2007,7 @@ module.exports = class acx extends Exchange { const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, BadSymbol, InvalidOrder, PermissionDenied, InvalidAddress, AuthenticationError, InvalidNonce, BadRequest, InsufficientFunds, OrderNotFound } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -2655,8 +2196,8 @@ module.exports = class aofex extends Exchange { const symbol = base + '/' + quote; const numericId = this.safeInteger (market, 'id'); const precision = this.safeValue (precisions, id, {}); - const makerFee = this.safeFloat (market, 'maker_fee'); - const takerFee = this.safeFloat (market, 'taker_fee'); + const makerFee = this.safeNumber (market, 'maker_fee'); + const takerFee = this.safeNumber (market, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -2674,12 +2215,12 @@ module.exports = class aofex extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -2707,11 +2248,11 @@ module.exports = class aofex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -2790,11 +2331,11 @@ module.exports = class aofex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -2817,8 +2358,8 @@ module.exports = class aofex extends Exchange { return { 'info': response, 'symbol': symbol, - 'maker': this.safeFloat (result, 'fromFee'), - 'taker': this.safeFloat (result, 'toFee'), + 'maker': this.safeNumber (result, 'fromFee'), + 'taker': this.safeNumber (result, 'toFee'), }; } @@ -2875,8 +2416,8 @@ module.exports = class aofex extends Exchange { if (market) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); let change = undefined; if (symbol !== undefined) { change = parseFloat (this.priceToPrecision (symbol, last - open)); @@ -2885,8 +2426,8 @@ module.exports = class aofex extends Exchange { } const average = this.sum (last, open) / 2; const percentage = change / open * 100; - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); let vwap = this.vwap (baseVolume, quoteVolume); if (vwap !== undefined) { vwap = parseFloat (this.priceToPrecision (symbol, vwap)); @@ -2895,8 +2436,8 @@ module.exports = class aofex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -3014,13 +2555,15 @@ module.exports = class aofex extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'number'); - let cost = this.safeFloat (trade, 'total_price'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'number'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total_price'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -3164,21 +2707,21 @@ module.exports = class aofex extends Exchange { const orderType = this.safeString (order, 'type'); const type = (orderType === '2') ? 'limit' : 'market'; const side = this.safeString (order, 'side'); - // const amount = this.safeFloat (order, 'number'); - // const price = this.safeFloat (order, 'price'); + // const amount = this.safeNumber (order, 'number'); + // const price = this.safeNumber (order, 'price'); let cost = undefined; let price = undefined; let amount = undefined; let average = undefined; - const number = this.safeFloat (order, 'number'); - const totalPrice = this.safeFloat (order, 'total_price'); + const number = this.safeNumber (order, 'number'); + const totalPrice = this.safeNumber (order, 'total_price'); if (type === 'limit') { amount = number; - price = this.safeFloat (order, 'price'); + price = this.safeNumber (order, 'price'); } else { - average = this.safeFloat (order, 'deal_price'); + average = this.safeNumber (order, 'deal_price'); if (side === 'buy') { - amount = this.safeFloat (order, 'deal_number'); + amount = this.safeNumber (order, 'deal_number'); } else { amount = number; } @@ -3561,7 +3104,1693 @@ module.exports = class aofex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],6:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],5:[function(require,module,exports){ +'use strict'; + +// --------------------------------------------------------------------------- + +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); + +// --------------------------------------------------------------------------- + +module.exports = class ascendex extends Exchange { + describe () { + return this.deepExtend (super.describe (), { + 'id': 'ascendex', + 'name': 'AscendEX', + 'countries': [ 'SG', 'CN' ], // Singapore, China + 'rateLimit': 500, + // new metainfo interface + 'has': { + 'CORS': false, + 'fetchMarkets': true, + 'fetchCurrencies': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchOHLCV': true, + 'fetchTrades': true, + 'fetchAccounts': true, + 'fetchBalance': true, + 'createOrder': true, + 'cancelOrder': true, + 'cancelAllOrders': true, + 'fetchDepositAddress': true, + 'fetchTransactions': true, + 'fetchDeposits': true, + 'fetchWithdrawals': true, + 'fetchOrder': true, + 'fetchOrders': true, + 'fetchOpenOrders': true, + 'fetchClosedOrders': true, + }, + 'timeframes': { + '1m': '1', + '5m': '5', + '15m': '15', + '30m': '30', + '1h': '60', + '2h': '120', + '4h': '240', + '6h': '360', + '12h': '720', + '1d': '1d', + '1w': '1w', + '1M': '1m', + }, + 'version': 'v1', + 'urls': { + 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg', + 'api': 'https://ascendex.com', + 'test': 'https://bitmax-test.io', + 'www': 'https://ascendex.com', + 'doc': [ + 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', + ], + 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate', + 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', + }, + 'api': { + 'public': { + 'get': [ + 'assets', + 'products', + 'ticker', + 'barhist/info', + 'barhist', + 'depth', + 'trades', + 'cash/assets', // not documented + 'cash/products', // not documented + 'margin/assets', // not documented + 'margin/products', // not documented + 'futures/collateral', + 'futures/contracts', + 'futures/ref-px', + 'futures/market-data', + 'futures/funding-rates', + ], + }, + 'accountCategory': { + 'get': [ + 'balance', + 'order/open', + 'order/status', + 'order/hist/current', + 'risk', + ], + 'post': [ + 'order', + 'order/batch', + ], + 'delete': [ + 'order', + 'order/all', + 'order/batch', + ], + }, + 'accountGroup': { + 'get': [ + 'cash/balance', + 'margin/balance', + 'margin/risk', + 'transfer', + 'futures/collateral-balance', + 'futures/position', + 'futures/risk', + 'futures/funding-payments', + 'order/hist', + ], + 'post': [ + 'futures/transfer/deposit', + 'futures/transfer/withdraw', + ], + }, + 'private': { + 'get': [ + 'info', + 'wallet/transactions', + 'wallet/deposit/address', // not documented + ], + }, + }, + 'fees': { + 'trading': { + 'feeSide': 'get', + 'tierBased': true, + 'percentage': true, + 'taker': 0.002, + 'maker': 0.002, + }, + }, + 'precisionMode': TICK_SIZE, + 'options': { + 'account-category': 'cash', // 'cash'/'margin'/'futures' + 'account-group': undefined, + 'fetchClosedOrders': { + 'method': 'accountGroupGetOrderHist', // 'accountGroupGetAccountCategoryOrderHistCurrent' + }, + }, + 'exceptions': { + 'exact': { + // not documented + '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"} + '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"} + '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"} + '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."} + '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'} + '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' } + '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."} + // documented + '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid + '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing + '100003': BadRequest, // KEY_CONFLICT The same key exists already + '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument + '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument + '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid + '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption + '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request + '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request + '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account + '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp + '100012': BadRequest, // INVALID_STR_FORMAT String format does not + '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input + '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error + '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object + '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed + '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times + '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist + '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly + '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist + '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error + '200007': ExchangeError, // CODE_NOT_FOUND + '200008': ExchangeError, // CODE_EXPIRED Code expired + '200009': ExchangeError, // CODE_MISMATCH Code does not match + '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword + '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly + '200012': ExchangeError, // FAKE_COKE_VERIFY + '200013': ExchangeError, // SECURITY_ALERT Provide security alert message + '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw. + '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation + '300001': InvalidOrder, // INVALID_PRICE Order price is invalid + '300002': InvalidOrder, // INVALID_QTY Order size is invalid + '300003': InvalidOrder, // INVALID_SIDE Order side is invalid + '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large + '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid + '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid + '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid + '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid + '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset + '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading + '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange + '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request + '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset + '300021': InvalidOrder, // TRADING_DISABLED Trading is disabled on account or asset + '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading + '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance + '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading + '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high + '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading + '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price + '510001': ExchangeError, // SERVER_ERROR Something wrong with server. + '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass + }, + 'broad': {}, + }, + 'commonCurrencies': { + 'BOND': 'BONDED', + 'BTCBEAR': 'BEAR', + 'BTCBULL': 'BULL', + }, + }); + } + + getAccount (params = {}) { + // get current or provided bitmax sub-account + const account = this.safeValue (params, 'account', this.options['account']); + return account.toLowerCase ().capitalize (); + } + + async fetchCurrencies (params = {}) { + const assets = await this.publicGetAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode" : "LTCBULL", + // "assetName" : "3X Long LTC Token", + // "precisionScale" : 9, + // "nativeScale" : 4, + // "withdrawalFee" : "0.2", + // "minWithdrawalAmt" : "1.0", + // "status" : "Normal" + // }, + // ] + // } + // + const margin = await this.publicGetMarginAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode":"BTT", + // "borrowAssetCode":"BTT-B", + // "interestAssetCode":"BTT-I", + // "nativeScale":0, + // "numConfirmations":1, + // "withdrawFee":"100.0", + // "minWithdrawalAmt":"1000.0", + // "statusCode":"Normal", + // "statusMessage":"", + // "interestRate":"0.001" + // } + // ] + // } + // + const cash = await this.publicGetCashAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode":"LTCBULL", + // "nativeScale":4, + // "numConfirmations":20, + // "withdrawFee":"0.2", + // "minWithdrawalAmt":"1.0", + // "statusCode":"Normal", + // "statusMessage":"" + // } + // ] + // } + // + const assetsData = this.safeValue (assets, 'data', []); + const marginData = this.safeValue (margin, 'data', []); + const cashData = this.safeValue (cash, 'data', []); + const assetsById = this.indexBy (assetsData, 'assetCode'); + const marginById = this.indexBy (marginData, 'assetCode'); + const cashById = this.indexBy (cashData, 'assetCode'); + const dataById = this.deepExtend (assetsById, marginById, cashById); + const ids = Object.keys (dataById); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + const currency = dataById[id]; + const code = this.safeCurrencyCode (id); + const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); + // why would the exchange API have different names for the same field + const fee = this.safeNumber2 (currency, 'withdrawFee', 'withdrawalFee'); + const status = this.safeString2 (currency, 'status', 'statusCode'); + const active = (status === 'Normal'); + const margin = ('borrowAssetCode' in currency); + result[code] = { + 'id': id, + 'code': code, + 'info': currency, + 'type': undefined, + 'margin': margin, + 'name': this.safeString (currency, 'assetName'), + 'active': active, + 'fee': fee, + 'precision': precision, + 'limits': { + 'amount': { + 'min': Math.pow (10, -precision), + 'max': undefined, + }, + 'price': { + 'min': Math.pow (10, -precision), + 'max': undefined, + }, + 'cost': { + 'min': undefined, + 'max': undefined, + }, + 'withdraw': { + 'min': this.safeNumber (currency, 'minWithdrawalAmt'), + 'max': undefined, + }, + }, + }; + } + return result; + } + + async fetchMarkets (params = {}) { + const products = await this.publicGetProducts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"LBA/BTC", + // "baseAsset":"LBA", + // "quoteAsset":"BTC", + // "status":"Normal", + // "minNotional":"0.000625", + // "maxNotional":"6.25", + // "marginTradable":false, + // "commissionType":"Quote", + // "commissionReserveRate":"0.001", + // "tickSize":"0.000000001", + // "lotSize":"1" + // }, + // ] + // } + // + const cash = await this.publicGetCashProducts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"QTUM/BTC", + // "domain":"BTC", + // "tradingStartTime":1569506400000, + // "collapseDecimals":"0.0001,0.000001,0.00000001", + // "minQty":"0.000000001", + // "maxQty":"1000000000", + // "minNotional":"0.000625", + // "maxNotional":"12.5", + // "statusCode":"Normal", + // "statusMessage":"", + // "tickSize":"0.00000001", + // "useTick":false, + // "lotSize":"0.1", + // "useLot":false, + // "commissionType":"Quote", + // "commissionReserveRate":"0.001", + // "qtyScale":1, + // "priceScale":8, + // "notionalScale":4 + // } + // ] + // } + // + const futures = await this.publicGetFuturesContracts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"BTC-PERP", + // "tradingStartTime":1579701600000, + // "collapseDecimals":"1,0.1,0.01", + // "minQty":"0.000000001", + // "maxQty":"1000000000", + // "minNotional":"5", + // "maxNotional":"1000000", + // "statusCode":"Normal", + // "statusMessage":"", + // "tickSize":"0.25", + // "lotSize":"0.0001", + // "priceScale":2, + // "qtyScale":4, + // "notionalScale":2 + // } + // ] + // } + // + const productsData = this.safeValue (products, 'data', []); + const productsById = this.indexBy (productsData, 'symbol'); + const cashData = this.safeValue (cash, 'data', []); + const futuresData = this.safeValue (futures, 'data', []); + const cashAndFuturesData = this.arrayConcat (cashData, futuresData); + const cashAndFuturesById = this.indexBy (cashAndFuturesData, 'symbol'); + const dataById = this.deepExtend (productsById, cashAndFuturesById); + const ids = Object.keys (dataById); + const result = []; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + const market = dataById[id]; + const baseId = this.safeString (market, 'baseAsset'); + const quoteId = this.safeString (market, 'quoteAsset'); + const base = this.safeCurrencyCode (baseId); + const quote = this.safeCurrencyCode (quoteId); + const precision = { + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), + }; + const status = this.safeString (market, 'status'); + const active = (status === 'Normal'); + const type = ('useLot' in market) ? 'spot' : 'future'; + const spot = (type === 'spot'); + const future = (type === 'future'); + let symbol = id; + if (!future) { + symbol = base + '/' + quote; + } + result.push ({ + 'id': id, + 'symbol': symbol, + 'base': base, + 'quote': quote, + 'baseId': baseId, + 'quoteId': quoteId, + 'info': market, + 'type': type, + 'spot': spot, + 'future': future, + 'active': active, + 'precision': precision, + 'limits': { + 'amount': { + 'min': this.safeNumber (market, 'minQty'), + 'max': this.safeNumber (market, 'maxQty'), + }, + 'price': { + 'min': this.safeNumber (market, 'tickSize'), + 'max': undefined, + }, + 'cost': { + 'min': this.safeNumber (market, 'minNotional'), + 'max': this.safeNumber (market, 'maxNotional'), + }, + }, + }); + } + return result; + } + + async fetchAccounts (params = {}) { + let accountGroup = this.safeString (this.options, 'account-group'); + let response = undefined; + if (accountGroup === undefined) { + response = await this.privateGetInfo (params); + // + // { + // "code":0, + // "data":{ + // "email":"igor.kroitor@gmail.com", + // "accountGroup":8, + // "viewPermission":true, + // "tradePermission":true, + // "transferPermission":true, + // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"], + // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"], + // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"], + // "userUID":"U6491137460" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + accountGroup = this.safeString (data, 'accountGroup'); + this.options['account-group'] = accountGroup; + } + return [ + { + 'id': accountGroup, + 'type': undefined, + 'currency': undefined, + 'info': response, + }, + ]; + } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchBalance', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeString (account, 'id'); + const request = { + 'account-group': accountGroup, + }; + let method = 'accountCategoryGetBalance'; + if (accountCategory === 'futures') { + method = 'accountGroupGetFuturesCollateralBalance'; + } else { + request['account-category'] = accountCategory; + } + const response = await this[method] (this.extend (request, params)); + // + // cash + // + // { + // 'code': 0, + // 'data': [ + // { + // 'asset': 'BCHSV', + // 'totalBalance': '64.298000048', + // 'availableBalance': '64.298000048', + // }, + // ] + // } + // + // margin + // + // { + // 'code': 0, + // 'data': [ + // { + // 'asset': 'BCHSV', + // 'totalBalance': '64.298000048', + // 'availableBalance': '64.298000048', + // 'borrowed': '0', + // 'interest': '0', + // }, + // ] + // } + // + // futures + // + // { + // "code":0, + // "data":[ + // {"asset":"BTC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"9456.59"}, + // {"asset":"ETH","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"235.95"}, + // {"asset":"USDT","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"}, + // {"asset":"USDC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00035"}, + // {"asset":"PAX","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00045"}, + // {"asset":"USDTR","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"} + // ] + // } + // + const result = { 'info': response }; + const balances = this.safeValue (response, 'data', []); + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); + const account = this.account (); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async fetchOrderBook (symbol, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + const response = await this.publicGetDepth (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "m":"depth-snapshot", + // "symbol":"BTC-PERP", + // "data":{ + // "ts":1590223998202, + // "seqnum":115444921, + // "asks":[ + // ["9207.5","18.2383"], + // ["9207.75","18.8235"], + // ["9208","10.7873"], + // ], + // "bids":[ + // ["9207.25","0.4009"], + // ["9207","0.003"], + // ["9206.5","0.003"], + // ] + // } + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const orderbook = this.safeValue (data, 'data', {}); + const timestamp = this.safeInteger (orderbook, 'ts'); + const result = this.parseOrderBook (orderbook, timestamp); + result['nonce'] = this.safeInteger (orderbook, 'seqnum'); + return result; + } + + parseTicker (ticker, market = undefined) { + // + // { + // "symbol":"QTUM/BTC", + // "open":"0.00016537", + // "close":"0.00019077", + // "high":"0.000192", + // "low":"0.00016537", + // "volume":"846.6", + // "ask":["0.00018698","26.2"], + // "bid":["0.00018408","503.7"], + // "type":"spot" + // } + // + const timestamp = undefined; + const marketId = this.safeString (ticker, 'symbol'); + let symbol = undefined; + if (marketId in this.markets_by_id) { + market = this.markets_by_id[marketId]; + } else if (marketId !== undefined) { + const type = this.safeString (ticker, 'type'); + if (type === 'spot') { + const [ baseId, quoteId ] = marketId.split ('/'); + const base = this.safeCurrencyCode (baseId); + const quote = this.safeCurrencyCode (quoteId); + symbol = base + '/' + quote; + } + } + if ((symbol === undefined) && (market !== undefined)) { + symbol = market['symbol']; + } + const close = this.safeNumber (ticker, 'close'); + const bid = this.safeValue (ticker, 'bid', []); + const ask = this.safeValue (ticker, 'ask', []); + const open = this.safeNumber (ticker, 'open'); + let change = undefined; + let percentage = undefined; + let average = undefined; + if ((open !== undefined) && (close !== undefined)) { + change = close - open; + if (open > 0) { + percentage = change / open * 100; + } + average = this.sum (open, close) / 2; + } + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 0), + 'bidVolume': this.safeNumber (bid, 1), + 'ask': this.safeNumber (ask, 0), + 'askVolume': this.safeNumber (ask, 1), + 'vwap': undefined, + 'open': open, + 'close': close, + 'last': close, + 'previousClose': undefined, // previous day close + 'change': change, + 'percentage': percentage, + 'average': average, + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + const response = await this.publicGetTicker (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "symbol":"BTC-PERP", // or "BTC/USDT" + // "open":"9073", + // "close":"9185.75", + // "high":"9185.75", + // "low":"9185.75", + // "volume":"576.8334", + // "ask":["9185.75","15.5863"], + // "bid":["9185.5","0.003"], + // "type":"derivatives", // or "spot" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + return this.parseTicker (data, market); + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (symbols !== undefined) { + const marketIds = this.marketIds (symbols); + request['symbol'] = marketIds.join (','); + } + const response = await this.publicGetTicker (this.extend (request, params)); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"QTUM/BTC", + // "open":"0.00016537", + // "close":"0.00019077", + // "high":"0.000192", + // "low":"0.00016537", + // "volume":"846.6", + // "ask":["0.00018698","26.2"], + // "bid":["0.00018408","503.7"], + // "type":"spot" + // } + // ] + // } + // + const data = this.safeValue (response, 'data', []); + return this.parseTickers (data, symbols); + } + + parseOHLCV (ohlcv, market = undefined) { + // + // { + // "m":"bar", + // "s":"BTC/USDT", + // "data":{ + // "i":"1", + // "ts":1590228000000, + // "o":"9139.59", + // "c":"9131.94", + // "h":"9139.99", + // "l":"9121.71", + // "v":"25.20648" + // } + // } + // + const data = this.safeValue (ohlcv, 'data', {}); + return [ + this.safeInteger (data, 'ts'), + this.safeNumber (data, 'o'), + this.safeNumber (data, 'h'), + this.safeNumber (data, 'l'), + this.safeNumber (data, 'c'), + this.safeNumber (data, 'v'), + ]; + } + + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + 'interval': this.timeframes[timeframe], + }; + // if since and limit are not specified + // the exchange will return just 1 last candle by default + const duration = this.parseTimeframe (timeframe); + const options = this.safeValue (this.options, 'fetchOHLCV', {}); + const defaultLimit = this.safeInteger (options, 'limit', 500); + if (since !== undefined) { + request['from'] = since; + if (limit === undefined) { + limit = defaultLimit; + } else { + limit = Math.min (limit, defaultLimit); + } + request['to'] = this.sum (since, limit * duration * 1000, 1); + } else if (limit !== undefined) { + request['n'] = limit; // max 500 + } + const response = await this.publicGetBarhist (this.extend (request, params)); + // + // { + // "code":0, + // "data":[ + // { + // "m":"bar", + // "s":"BTC/USDT", + // "data":{ + // "i":"1", + // "ts":1590228000000, + // "o":"9139.59", + // "c":"9131.94", + // "h":"9139.99", + // "l":"9121.71", + // "v":"25.20648" + // } + // } + // ] + // } + // + const data = this.safeValue (response, 'data', []); + return this.parseOHLCVs (data, market, timeframe, since, limit); + } + + parseTrade (trade, market = undefined) { + // + // public fetchTrades + // + // { + // "p":"9128.5", // price + // "q":"0.0030", // quantity + // "ts":1590229002385, // timestamp + // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade + // "seqnum":180143985289898554 + // } + // + const timestamp = this.safeInteger (trade, 'ts'); + const priceString = this.safeString2 (trade, 'price', 'p'); + const amountString = this.safeString (trade, 'q'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const buyerIsMaker = this.safeValue (trade, 'bm', false); + const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; + const side = buyerIsMaker ? 'buy' : 'sell'; + let symbol = undefined; + if ((symbol === undefined) && (market !== undefined)) { + symbol = market['symbol']; + } + return { + 'info': trade, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'symbol': symbol, + 'id': undefined, + 'order': undefined, + 'type': undefined, + 'takerOrMaker': makerOrTaker, + 'side': side, + 'price': price, + 'amount': amount, + 'cost': cost, + 'fee': undefined, + }; + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + if (limit !== undefined) { + request['n'] = limit; // max 100 + } + const response = await this.publicGetTrades (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "m":"trades", + // "symbol":"BTC-PERP", + // "data":[ + // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554}, + // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587}, + // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043} + // ] + // } + // } + // + const records = this.safeValue (response, 'data', []); + const trades = this.safeValue (records, 'data', []); + return this.parseTrades (trades, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'PendingNew': 'open', + 'New': 'open', + 'PartiallyFilled': 'open', + 'Filled': 'closed', + 'Canceled': 'canceled', + 'Rejected': 'rejected', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + // + // createOrder + // + // { + // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", + // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", + // "orderType": "Market", + // "symbol": "BTC/USDT", + // "timestamp": 1573576916201 + // } + // + // fetchOrder, fetchOpenOrders, fetchClosedOrders + // + // { + // "symbol": "BTC/USDT", + // "price": "8131.22", + // "orderQty": "0.00082", + // "orderType": "Market", + // "avgPx": "7392.02", + // "cumFee": "0.005152238", + // "cumFilledQty": "0.00082", + // "errorCode": "", + // "feeAsset": "USDT", + // "lastExecTime": 1575953151764, + // "orderId": "a16eee20b6750866943712zWEDdAjt3", + // "seqNum": 2623469, + // "side": "Buy", + // "status": "Filled", + // "stopPrice": "", + // "execInst": "NULL_VAL" + // } + // + // { + // "ac": "FUTURES", + // "accountId": "testabcdefg", + // "avgPx": "0", + // "cumFee": "0", + // "cumQty": "0", + // "errorCode": "NULL_VAL", + // "execInst": "NULL_VAL", + // "feeAsset": "USDT", + // "lastExecTime": 1584072844085, + // "orderId": "r170d21956dd5450276356bbtcpKa74", + // "orderQty": "1.1499", + // "orderType": "Limit", + // "price": "4000", + // "sendingTime": 1584072841033, + // "seqNum": 24105338, + // "side": "Buy", + // "status": "Canceled", + // "stopPrice": "", + // "symbol": "BTC-PERP" + // }, + // + const status = this.parseOrderStatus (this.safeString (order, 'status')); + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '/'); + const timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); + const lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const average = this.safeNumber (order, 'avgPx'); + const filled = this.safeNumber2 (order, 'cumFilledQty', 'cumQty'); + const id = this.safeString (order, 'orderId'); + let clientOrderId = this.safeString (order, 'id'); + if (clientOrderId !== undefined) { + if (clientOrderId.length < 1) { + clientOrderId = undefined; + } + } + const type = this.safeStringLower (order, 'orderType'); + const side = this.safeStringLower (order, 'side'); + const feeCost = this.safeNumber (order, 'cumFee'); + let fee = undefined; + if (feeCost !== undefined) { + const feeCurrencyId = this.safeString (order, 'feeAsset'); + const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); + fee = { + 'cost': feeCost, + 'currency': feeCurrencyCode, + }; + } + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ + 'info': order, + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': lastTradeTimestamp, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': price, + 'stopPrice': stopPrice, + 'amount': amount, + 'cost': undefined, + 'average': average, + 'filled': filled, + 'remaining': undefined, + 'status': status, + 'fee': fee, + 'trades': undefined, + }); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const market = this.market (symbol); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'createOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'symbol': market['id'], + 'time': this.milliseconds (), + 'orderQty': this.amountToPrecision (symbol, amount), + 'orderType': type, // "limit", "market", "stop_market", "stop_limit" + 'side': side, // "buy" or "sell" + // 'orderPrice': this.priceToPrecision (symbol, price), + // 'stopPrice': this.priceToPrecision (symbol, stopPrice), // required for stop orders + // 'postOnly': 'false', // 'false', 'true' + // 'timeInForce': 'GTC', // GTC, IOC, FOK + // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE + }; + if (clientOrderId !== undefined) { + request['id'] = clientOrderId; + params = this.omit (params, [ 'clientOrderId', 'id' ]); + } + if ((type === 'limit') || (type === 'stop_limit')) { + request['orderPrice'] = this.priceToPrecision (symbol, price); + } + if ((type === 'stop_limit') || (type === 'stop_market')) { + const stopPrice = this.safeNumber (params, 'stopPrice'); + if (stopPrice === undefined) { + throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); + } else { + request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); + params = this.omit (params, 'stopPrice'); + } + } + const response = await this.accountCategoryPostOrder (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "ac": "MARGIN", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "action": "place-order", + // "info": { + // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", + // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", + // "orderType": "Market", + // "symbol": "BTC/USDT", + // "timestamp": 1573576916201 + // }, + // "status": "Ack" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const info = this.safeValue (data, 'info', {}); + return this.parseOrder (info, market); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'orderId': id, + }; + const response = await this.accountCategoryGetOrderStatus (this.extend (request, params)); + // + // { + // "code": 0, + // "accountCategory": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "data": [ + // { + // "symbol": "BTC/USDT", + // "price": "8131.22", + // "orderQty": "0.00082", + // "orderType": "Market", + // "avgPx": "7392.02", + // "cumFee": "0.005152238", + // "cumFilledQty": "0.00082", + // "errorCode": "", + // "feeAsset": "USDT", + // "lastExecTime": 1575953151764, + // "orderId": "a16eee20b6750866943712zWEDdAjt3", + // "seqNum": 2623469, + // "side": "Buy", + // "status": "Filled", + // "stopPrice": "", + // "execInst": "NULL_VAL" + // } + // ] + // } + // + const data = this.safeValue (response, 'data', {}); + return this.parseOrder (data); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + } + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchOpenOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + }; + const response = await this.accountCategoryGetOrderOpen (this.extend (request, params)); + // + // { + // "ac": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "code": 0, + // "data": [ + // { + // "avgPx": "0", // Average filled price of the order + // "cumFee": "0", // cumulative fee paid for this order + // "cumFilledQty": "0", // cumulative filled quantity + // "errorCode": "", // error code; could be empty + // "feeAsset": "USDT", // fee asset + // "lastExecTime": 1576019723550, // The last execution time of the order + // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId + // "orderQty": "0.0083", // order quantity + // "orderType": "Limit", // order type + // "price": "7105", // order price + // "seqNum": 8193258, // sequence number + // "side": "Buy", // order side + // "status": "New", // order status on matching engine + // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty + // "symbol": "BTC/USDT", + // "execInst": "NULL_VAL" // execution instruction + // }, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + if (accountCategory === 'futures') { + return this.parseOrders (data, market, since, limit); + } + // a workaround for https://github.com/ccxt/ccxt/issues/7187 + const orders = []; + for (let i = 0; i < data.length; i++) { + const order = this.parseOrder (data[i], market); + orders.push (order); + } + return this.filterBySymbolSinceLimit (orders, symbol, since, limit); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + } + const defaultAccountCategory = this.safeString (this.options, 'account-category'); + const options = this.safeValue (this.options, 'fetchClosedOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + // 'category': accountCategory, + // 'symbol': market['id'], + // 'orderType': 'market', // optional, string + // 'side': 'buy', // or 'sell', optional, case insensitive. + // 'status': 'Filled', // "Filled", "Canceled", or "Rejected" + // 'startTime': exchange.milliseconds (), + // 'endTime': exchange.milliseconds (), + // 'page': 1, + // 'pageSize': 100, + }; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const method = this.safeValue (options, 'method', 'accountGroupGetOrderHist'); + if (method === 'accountGroupGetOrderHist') { + if (accountCategory !== undefined) { + request['category'] = accountCategory; + } + } else { + request['account-category'] = accountCategory; + } + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['pageSize'] = limit; + } + const response = await this[method] (this.extend (request, params)); + // + // accountCategoryGetOrderHistCurrent + // + // { + // "code":0, + // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda", + // "ac":"CASH", + // "data":[ + // { + // "seqNum":15561826728, + // "orderId":"a17294d305c0U6491137460bethu7kw9", + // "symbol":"ETH/USDT", + // "orderType":"Limit", + // "lastExecTime":1591635618200, + // "price":"200", + // "orderQty":"0.1", + // "side":"Buy", + // "status":"Canceled", + // "avgPx":"0", + // "cumFilledQty":"0", + // "stopPrice":"", + // "errorCode":"", + // "cumFee":"0", + // "feeAsset":"USDT", + // "execInst":"NULL_VAL" + // } + // ] + // } + // + // accountGroupGetOrderHist + // + // { + // "code": 0, + // "data": { + // "data": [ + // { + // "ac": "FUTURES", + // "accountId": "testabcdefg", + // "avgPx": "0", + // "cumFee": "0", + // "cumQty": "0", + // "errorCode": "NULL_VAL", + // "execInst": "NULL_VAL", + // "feeAsset": "USDT", + // "lastExecTime": 1584072844085, + // "orderId": "r170d21956dd5450276356bbtcpKa74", + // "orderQty": "1.1499", + // "orderType": "Limit", + // "price": "4000", + // "sendingTime": 1584072841033, + // "seqNum": 24105338, + // "side": "Buy", + // "status": "Canceled", + // "stopPrice": "", + // "symbol": "BTC-PERP" + // }, + // ], + // "hasNext": False, + // "limit": 500, + // "page": 1, + // "pageSize": 20 + // } + // } + // + let data = this.safeValue (response, 'data'); + const isArray = Array.isArray (data); + if (!isArray) { + data = this.safeValue (data, 'data', []); + } + return this.parseOrders (data, market, since, limit); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument'); + } + await this.loadMarkets (); + await this.loadAccounts (); + const market = this.market (symbol); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'cancelOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'symbol': market['id'], + 'time': this.milliseconds (), + 'id': 'foobar', + }; + if (clientOrderId === undefined) { + request['orderId'] = id; + } else { + request['id'] = clientOrderId; + params = this.omit (params, [ 'clientOrderId', 'id' ]); + } + const response = await this.accountCategoryDeleteOrder (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "ac": "CASH", + // "action": "cancel-order", + // "status": "Ack", + // "info": { + // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23", + // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc", + // "orderType": "", // could be empty + // "symbol": "ETH/USDT", + // "timestamp": 1573594877822 + // } + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const info = this.safeValue (data, 'info', {}); + return this.parseOrder (info, market); + } + + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'cancelAllOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'time': this.milliseconds (), + }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.accountCategoryDeleteOrderAll (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "ac": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "action": "cancel-all", + // "info": { + // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy", + // "orderId": "", + // "orderType": "NULL_VAL", + // "symbol": "", + // "timestamp": 1574118495462 + // }, + // "status": "Ack" + // } + // } + // + return response; + } + + parseDepositAddress (depositAddress, currency = undefined) { + // + // { + // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // destTag: "", + // tagType: "", + // tagId: "", + // chainName: "ERC20", + // numConfirmations: 20, + // withdrawalFee: 1, + // nativeScale: 4, + // tips: [] + // } + // + const address = this.safeString (depositAddress, 'address'); + const tagId = this.safeString (depositAddress, 'tagId'); + const tag = this.safeString (depositAddress, tagId); + this.checkAddress (address); + const code = (currency === undefined) ? undefined : currency['code']; + return { + 'currency': code, + 'address': address, + 'tag': tag, + 'info': depositAddress, + }; + } + + async fetchDepositAddress (code, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const chainName = this.safeString (params, 'chainName'); + params = this.omit (params, 'chainName'); + const request = { + 'asset': currency['id'], + }; + const response = await this.privateGetWalletDepositAddress (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "asset":"USDT", + // "assetName":"Tether", + // "address":[ + // { + // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6", + // "destTag":"", + // "tagType":"", + // "tagId":"", + // "chainName":"Omni", + // "numConfirmations":3, + // "withdrawalFee":4.7, + // "nativeScale":4, + // "tips":[] + // }, + // { + // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // "destTag":"", + // "tagType":"", + // "tagId":"", + // "chainName":"ERC20", + // "numConfirmations":20, + // "withdrawalFee":1.0, + // "nativeScale":4, + // "tips":[] + // } + // ] + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const addresses = this.safeValue (data, 'address', []); + const numAddresses = addresses.length; + let address = undefined; + if (numAddresses > 1) { + const addressesByChainName = this.indexBy (addresses, 'chainName'); + if (chainName === undefined) { + const chainNames = Object.keys (addressesByChainName); + const chains = chainNames.join (', '); + throw new ArgumentsRequired (this.id + ' fetchDepositAddress returned more than one address, a chainName parameter is required, one of ' + chains); + } + address = this.safeValue (addressesByChainName, chainName, {}); + } else { + // first address + address = this.safeValue (addresses, 0, {}); + } + const result = this.parseDepositAddress (address, currency); + return this.extend (result, { + 'info': response, + }); + } + + async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'txType': 'deposit', + }; + return await this.fetchTransactions (code, since, limit, this.extend (request, params)); + } + + async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'txType': 'withdrawal', + }; + return await this.fetchTransactions (code, since, limit, this.extend (request, params)); + } + + async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'asset': currency['id'], + // 'page': 1, + // 'pageSize': 20, + // 'startTs': this.milliseconds (), + // 'endTs': this.milliseconds (), + // 'txType': undefned, // deposit, withdrawal + }; + let currency = undefined; + if (code !== undefined) { + currency = this.currency (code); + request['asset'] = currency['id']; + } + if (since !== undefined) { + request['startTs'] = since; + } + if (limit !== undefined) { + request['pageSize'] = limit; + } + const response = await this.privateGetWalletTransactions (this.extend (request, params)); + // + // { + // code: 0, + // data: { + // data: [ + // { + // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", + // time: 1591606166000, + // asset: "USDT", + // transactionType: "deposit", + // amount: "25", + // commission: "0", + // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", + // status: "pending", + // numConfirmed: 8, + // numConfirmations: 20, + // destAddress: { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" } + // } + // ], + // page: 1, + // pageSize: 20, + // hasNext: false + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const transactions = this.safeValue (data, 'data', []); + return this.parseTransactions (transactions, currency, since, limit); + } + + parseTransactionStatus (status) { + const statuses = { + 'reviewing': 'pending', + 'pending': 'pending', + 'confirmed': 'ok', + 'rejected': 'rejected', + }; + return this.safeString (statuses, status, status); + } + + parseTransaction (transaction, currency = undefined) { + // + // { + // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", + // time: 1591606166000, + // asset: "USDT", + // transactionType: "deposit", + // amount: "25", + // commission: "0", + // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", + // status: "pending", + // numConfirmed: 8, + // numConfirmations: 20, + // destAddress: { + // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // destTag: "..." // for currencies that have it + // } + // } + // + const id = this.safeString (transaction, 'requestId'); + const amount = this.safeNumber (transaction, 'amount'); + const destAddress = this.safeValue (transaction, 'destAddress', {}); + const address = this.safeString (destAddress, 'address'); + const tag = this.safeString (destAddress, 'destTag'); + const txid = this.safeString (transaction, 'networkTransactionId'); + const type = this.safeString (transaction, 'transactionType'); + const timestamp = this.safeInteger (transaction, 'time'); + const currencyId = this.safeString (transaction, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); + const feeCost = this.safeNumber (transaction, 'commission'); + return { + 'info': transaction, + 'id': id, + 'currency': code, + 'amount': amount, + 'address': address, + 'addressTo': address, + 'addressFrom': undefined, + 'tag': tag, + 'tagTo': tag, + 'tagFrom': undefined, + 'status': status, + 'type': type, + 'updated': undefined, + 'txid': txid, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'fee': { + 'currency': code, + 'cost': feeCost, + }, + }; + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let url = ''; + let query = params; + const accountCategory = (api === 'accountCategory'); + if (accountCategory || (api === 'accountGroup')) { + url += this.implodeParams ('/{account-group}', params); + query = this.omit (params, 'account-group'); + } + const request = this.implodeParams (path, query); + url += '/api/pro/' + this.version; + if (accountCategory) { + url += this.implodeParams ('/{account-category}', query); + query = this.omit (query, 'account-category'); + } + url += '/' + request; + query = this.omit (query, this.extractParams (path)); + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const timestamp = this.milliseconds ().toString (); + const payload = timestamp + '+' + request; + const hmac = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64'); + headers = { + 'x-auth-key': this.apiKey, + 'x-auth-timestamp': timestamp, + 'x-auth-signature': hmac, + }; + if (method === 'GET') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + headers['Content-Type'] = 'application/json'; + body = this.json (query); + } + } + url = this.urls['api'] + url; + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; // fallback to default error handler + } + // + // {'code': 6010, 'message': 'Not enough balance.'} + // {'code': 60060, 'message': 'The order is already filled or canceled.'} + // {"code":2100,"message":"ApiKeyFailure"} + // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}} + // + const code = this.safeString (response, 'code'); + const message = this.safeString (response, 'message'); + const error = (code !== undefined) && (code !== '0'); + if (error || (message !== undefined)) { + const feedback = this.id + ' ' + body; + this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); + this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); + this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); + throw new ExchangeError (feedback); // unknown message + } + } +}; + +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],6:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -3608,6 +4837,7 @@ const { // eslint-disable-line object-curly-newline const { TRUNCATE, ROUND, DECIMAL_PLACES, NO_PADDING } = functions.precisionConstants const BN = require ('../static_dependencies/BN/bn') +const Precise = require ('./Precise') // ---------------------------------------------------------------------------- @@ -3788,6 +5018,11 @@ module.exports = class Exchange { this.minFundingAddressLength = 1 // used in checkAddress this.substituteCommonCurrencyCodes = true // reserved + this.quoteJsonNumbers = true // treat numbers in json as quoted precise strings + this.number = Number // or String (a pointer to a function) + + // whether fees should be summed by currency code + this.reduceFees = true // do not delete this line, it is needed for users to be able to define their own fetchImplementation this.fetchImplementation = defaultFetch @@ -4083,7 +5318,7 @@ module.exports = class Exchange { parseJson (jsonString) { try { if (this.isJsonEncodedObject (jsonString)) { - return JSON.parse (jsonString) + return JSON.parse (this.onJsonResponse (jsonString)) } } catch (e) { // SyntaxError @@ -4162,7 +5397,11 @@ module.exports = class Exchange { } onRestResponse (statusCode, statusText, url, method, responseHeaders, responseBody, requestHeaders, requestBody) { - return responseBody.trim ().replace (/:(\d{15,}),/g, ':"$1",'); + return responseBody.trim () + } + + onJsonResponse (responseBody) { + return this.quoteJsonNumbers ? responseBody.replace (/":([+.0-9eE-]+),/g, '":"$1",') : responseBody; } setMarkets (markets, currencies = undefined) { @@ -4482,8 +5721,8 @@ module.exports = class Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = parseFloat (bidask[priceKey]) - const amount = parseFloat (bidask[amountKey]) + const price = this.safeNumber (bidask, priceKey) + const amount = this.safeNumber (bidask, amountKey) return [ price, amount ] } @@ -4509,7 +5748,7 @@ module.exports = class Exchange { } } - parseBalance (balance) { + parseBalance (balance, legacy = true) { const codes = Object.keys (this.omit (balance, [ 'info', 'free', 'used', 'total' ])); @@ -4521,20 +5760,34 @@ module.exports = class Exchange { const code = codes[i] if (balance[code].total === undefined) { if (balance[code].free !== undefined && balance[code].used !== undefined) { - balance[code].total = this.sum (balance[code].free, balance[code].used) + if (legacy) { + balance[code].total = this.sum (balance[code].free, balance[code].used) + } else { + balance[code].total = Precise.stringAdd (balance[code].free, balance[code].used) + } } } if (balance[code].free === undefined) { if (balance[code].total !== undefined && balance[code].used !== undefined) { - balance[code].free = this.sum (balance[code].total, -balance[code].used) + if (legacy) { + balance[code].free = this.sum (balance[code].total, -balance[code].used) + } else { + balance[code].free = Precise.stringSub (balance[code].total, balance[code].used) + } } } if (balance[code].used === undefined) { if (balance[code].total !== undefined && balance[code].free !== undefined) { - balance[code].used = this.sum (balance[code].total, -balance[code].free) + if (legacy) { + balance[code].used = this.sum (balance[code].total, -balance[code].free) + } else { + balance[code].used = Precise.stringSub (balance[code].total, balance[code].free) + } } } - + balance[code].free = this.parseNumber (balance[code].free) + balance[code].used = this.parseNumber (balance[code].used) + balance[code].total = this.parseNumber (balance[code].total) balance.free[code] = balance[code].free balance.used[code] = balance[code].used balance.total[code] = balance[code].total @@ -4543,6 +5796,10 @@ module.exports = class Exchange { return balance } + async fetchBalance (params = {}) { + throw new NotSupported (this.id + ' fetchBalance not supported yet') + } + async fetchPartialBalance (part, params = {}) { const balance = await this.fetchBalance (params) return balance[part] @@ -4652,11 +5909,27 @@ module.exports = class Exchange { return indexed ? indexBy (result, key) : result } + parseTickers (tickers, symbols = undefined) { + const result = []; + for (let i = 0; i < tickers.length; i++) { + result.push (this.parseTicker (tickers[i])); + } + return this.filterByArray (result, 'symbol', symbols); + } + + parseDepositAddresses (addresses, codes = undefined) { + let result = []; + for (let i = 0; i < addresses.length; i++) { + const address = this.parseDepositAddress (addresses[i]); + result.push (address); + } + if (codes) { + result = this.filterByArray (result, 'currency', codes); + } + return this.indexBy (result, 'currency'); + } + parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (trades)) { - // throw new ExchangeError (this.id + ' parseTrades expected an array in the trades argument, but got ' + typeof trades); - // } let result = Object.values (trades || []).map ((trade) => this.extend (this.parseTrade (trade, market), params)) result = sortBy (result, 'timestamp') const symbol = (market !== undefined) ? market['symbol'] : undefined @@ -4665,10 +5938,6 @@ module.exports = class Exchange { } parseTransactions (transactions, currency = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (transactions)) { - // throw new ExchangeError (this.id + ' parseTransactions expected an array in the transactions argument, but got ' + typeof transactions); - // } let result = Object.values (transactions || []).map ((transaction) => this.extend (this.parseTransaction (transaction, currency), params)) result = this.sortBy (result, 'timestamp'); const code = (currency !== undefined) ? currency['code'] : undefined; @@ -4676,6 +5945,14 @@ module.exports = class Exchange { return this.filterByCurrencySinceLimit (result, code, since, limit, tail); } + parseTransfers (transfers, currency = undefined, since = undefined, limit = undefined, params = {}) { + let result = Object.values (transfers || []).map ((transfer) => this.extend (this.parseTransfer (transfer, currency), params)) + result = this.sortBy (result, 'timestamp'); + const code = (currency !== undefined) ? currency['code'] : undefined; + const tail = since === undefined; + return this.filterByCurrencySinceLimit (result, code, since, limit, tail); + } + parseLedger (data, currency = undefined, since = undefined, limit = undefined, params = {}) { let result = []; const array = Object.values (data || []); @@ -4820,19 +6097,19 @@ module.exports = class Exchange { return this.createOrder (symbol, ...args) } - createLimitOrder (symbol, side, amount, price = undefined, params = {}) { + createLimitOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'limit', side, amount, price, params) } - createMarketOrder (symbol, side, amount, price = undefined, params = {}) { + createMarketOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'market', side, amount, price, params) } - createLimitBuyOrder (symbol, amount, price = undefined, params = {}) { + createLimitBuyOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'buy', amount, price, params) } - createLimitSellOrder (symbol, amount, price = undefined, params = {}) { + createLimitSellOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'sell', amount, price, params) } @@ -4865,15 +6142,43 @@ module.exports = class Exchange { } calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol] - const rate = market[takerOrMaker] - const cost = parseFloat (this.costToPrecision (symbol, amount * price)) + const market = this.markets[symbol]; + const feeSide = this.safeString (market, 'feeSide', 'quote'); + let key = 'quote'; + let cost = undefined; + if (feeSide === 'quote') { + // the fee is always in quote currency + cost = amount * price; + } else if (feeSide === 'base') { + // the fee is always in base currency + cost = amount; + } else if (feeSide === 'get') { + // the fee is always in the currency you get + cost = amount; + if (side === 'sell') { + cost *= price; + } else { + key = 'base'; + } + } else if (feeSide === 'give') { + // the fee is always in the currency you give + cost = amount; + if (side === 'buy') { + cost *= price; + } else { + key = 'base'; + } + } + const rate = market[takerOrMaker]; + if (cost !== undefined) { + cost *= rate; + } return { 'type': takerOrMaker, - 'currency': market['quote'], + 'currency': market[key], 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, rate * cost)), - } + 'cost': cost, + }; } checkRequiredDependencies () { @@ -4957,6 +6262,25 @@ module.exports = class Exchange { return new BN (a).pow (new BN (b)) } + reduceFeesByCurrency (fees) { + const reduced = {}; + for (let i = 0; i < fees.length; i++) { + const fee = fees[i]; + const feeCurrencyCode = this.safeValue (fee, 'currency'); + if (feeCurrencyCode !== undefined) { + if (feeCurrencyCode in reduced) { + reduced[feeCurrencyCode]['cost'] = this.sum (reduced[feeCurrencyCode]['cost'], fee['cost']); + } else { + reduced[feeCurrencyCode] = { + 'cost': fee['cost'], + 'currency': feeCurrencyCode, + }; + } + } + } + return Object.values (reduced); + } + safeOrder (order) { // Cost // Remaining @@ -4965,70 +6289,295 @@ module.exports = class Exchange { // Amount // Filled // - // First we try to calculate filled from the trades - const parseFilled = order['filled'] === undefined; - const parseCost = order['cost'] === undefined; - if (parseFilled) { - order['filled'] = 0 - } - if (parseCost) { - order['cost'] = 0 - } - if (parseFilled || parseCost) { - if (Array.isArray (order['trades'])) { - for (let i = 0; i < order['trades'].length; i++) { - const trade = order['trades'][i] - if (parseFilled) { - order['filled'] = this.sum (order['filled'], trade['amount']) + // first we try to calculate the order fields from the trades + let amount = this.safeValue (order, 'amount'); + let remaining = this.safeValue (order, 'remaining'); + let filled = this.safeValue (order, 'filled'); + let cost = this.safeValue (order, 'cost'); + let average = this.safeValue (order, 'average'); + let price = this.safeValue (order, 'price'); + let lastTradeTimeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); + const parseFilled = (filled === undefined); + const parseCost = (cost === undefined); + const parseLastTradeTimeTimestamp = (lastTradeTimeTimestamp === undefined); + const parseFee = this.safeValue (order, 'fee') === undefined; + const parseFees = this.safeValue (order, 'fees') === undefined; + const shouldParseFees = parseFee || parseFees; + const fees = shouldParseFees ? [] : undefined; + if (parseFilled || parseCost || shouldParseFees) { + const trades = this.safeValue (order, 'trades'); + if (trades !== undefined) { + if (parseFilled) { + filled = 0; + } + if (parseCost) { + cost = 0; + } + for (let i = 0; i < trades.length; i++) { + const trade = trades[i]; + const tradeAmount = this.safeValue (trade, 'amount'); + if (parseFilled && (tradeAmount !== undefined)) { + filled = this.sum (filled, tradeAmount); } - if (parseCost) { - order['cost'] = this.sum (order['cost'], trade['cost']) + const tradeCost = this.safeValue (trade, 'cost'); + if (parseCost && (tradeCost !== undefined)) { + cost = this.sum (cost, tradeCost); + } + const tradeTimestamp = this.safeValue (trade, 'timestamp'); + if (parseLastTradeTimeTimestamp && (tradeTimestamp !== undefined)) { + if (lastTradeTimeTimestamp === undefined) { + lastTradeTimeTimestamp = tradeTimestamp; + } else { + lastTradeTimeTimestamp = Math.max (lastTradeTimeTimestamp, tradeTimestamp); + } + } + if (shouldParseFees) { + const tradeFees = this.safeValue (trade, 'fees'); + if (tradeFees !== undefined) { + for (let j = 0; j < tradeFees.length; j++) { + const tradeFee = tradeFees[j]; + fees.push (this.extend ({}, tradeFee)); + } + } else { + const tradeFee = this.safeValue (trade, 'fee'); + if (tradeFee !== undefined) { + fees.push (this.extend ({}, tradeFee)); + } + } } } } } - // We ensure amount = filled + remaining - if (order['amount'] === undefined) { - if (order['filled'] !== undefined && order['remaining'] !== undefined) { - order['amount'] = this.sum (order['filled'], order['remaining']) + if (shouldParseFees) { + const reducedFees = this.reduceFees ? this.reduceFeesByCurrency (fees) : fees; + const reducedLength = reducedFees.length; + if (!parseFee && (reducedLength === 0)) { + reducedFees.push (order['fee']); + } + if (parseFees) { + order['fees'] = reducedFees; + } + if (parseFee && (reducedLength === 1)) { + order['fee'] = reducedFees[0]; } } - if (order['filled'] === undefined) { - if (order['amount'] !== undefined && order['remaining'] !== undefined) { - order['filled'] = Math.max (this.sum (order['amount'], -order['remaining']), 0) + if (amount === undefined) { + // ensure amount = filled + remaining + if (filled !== undefined && remaining !== undefined) { + amount = this.sum (filled, remaining); + } else if (this.safeString (order, 'status') === 'closed') { + amount = filled; } } - if (order['remaining'] === undefined) { - if (order['amount'] !== undefined && order['filled'] !== undefined) { - order['remaining'] = Math.max (this.sum (order['amount'], -order['filled']), 0) + if (filled === undefined) { + if (amount !== undefined && remaining !== undefined) { + filled = Math.max (this.sum (amount, -remaining), 0); } } - // We ensure that the average field is calculated correctly - if (order['average'] === undefined) { - if (order['filled'] !== undefined && order['cost'] !== undefined && order['cost'] > 0) { - order['average'] = order['filled'] / order['cost'] + if (remaining === undefined) { + if (amount !== undefined && filled !== undefined) { + remaining = Math.max (this.sum (amount, -filled), 0); } } - // We also ensure the cost field is calculated correctly - const costPriceExists = (order['average'] !== undefined) || (order['price'] !== undefined) - if ((order['filled'] !== undefined) && costPriceExists) { - let costPrice = undefined; - if (order['average'] === undefined) { - costPrice = order['price'] - } else { - costPrice = order['average'] + // ensure that the average field is calculated correctly + if (average === undefined) { + if ((filled !== undefined) && (cost !== undefined) && (cost > 0)) { + average = cost / filled; } - order['cost'] = costPrice * order['filled'] } - // We add support for market orders - if (order['price'] === undefined && order['type'] === 'market') { - order['price'] = order['average'] + // also ensure the cost field is calculated correctly + const costPriceExists = (average !== undefined) || (price !== undefined); + if (parseCost && (filled !== undefined) && costPriceExists) { + cost = (average === undefined) ? (price * filled) : (average * filled); } - return order + // support for market orders + const orderType = this.safeValue (order, 'type'); + const emptyPrice = (price === undefined) || (price === 0.0); + if (emptyPrice && (orderType === 'market')) { + price = average; + } + return this.extend (order, { + 'lastTradeTimestamp': lastTradeTimeTimestamp, + 'price': price, + 'amount': amount, + 'cost': cost, + 'average': average, + 'filled': filled, + 'remaining': remaining, + }); + } + + parseNumber (value, d = undefined) { + if (value === undefined) { + return d + } else { + try { + return this.number (value) + } catch (e) { + return d + } + } + } + + safeNumber (object, key, d = undefined) { + const value = this.safeString (object, key) + return this.parseNumber (value, d) + } + + safeNumber2 (object, key1, key2, d = undefined) { + const value = this.safeString2 (object, key1, key2) + return this.parseNumber (value, d) } } -},{"../static_dependencies/BN/bn":126,"./errors":8,"./functions":9}],7:[function(require,module,exports){ +},{"../static_dependencies/BN/bn":123,"./Precise":7,"./errors":9,"./functions":10}],7:[function(require,module,exports){ +'use strict' + +const BN = require ('../static_dependencies/BN/bn') + +class Precise { + constructor (number, decimals = 0) { + const isBN = number instanceof BN + const isString = typeof number === 'string' + if (!(isBN || isString)) { + throw new Error ('Precise initiated with something other than a string or BN') + } + if (isBN) { + this.integer = number + this.decimals = decimals + } else { + if (decimals) { + throw new Error ('Cannot set decimals when initializing with a string') + } + let modifier = 0 + number = number.toLowerCase () + if (number.indexOf ('e') > -1) { + [ number, modifier ] = number.split ('e') + modifier = parseInt (modifier) + } + const decimalIndex = number.indexOf ('.') + this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0 + const integerString = number.replace ('.', '') + this.integer = new BN (integerString) + this.decimals = this.decimals - modifier + } + this.base = 10 + this.reduce () + } + + mul (other) { + // other must be another instance of Precise + const integerResult = this.integer.mul (other.integer) + return new Precise (integerResult, this.decimals + other.decimals) + } + + div (other, precision = 18) { + const distance = precision - this.decimals + other.decimals + let numerator + if (distance === 0) { + numerator = this.integer + } else if (distance < 0) { + const exponent = new BN (this.base).pow (new BN (-distance)) + numerator = this.integer.div (exponent) + } else { + const exponent = new BN (this.base).pow (new BN (distance)) + numerator = this.integer.mul (exponent) + } + const result = numerator.div (other.integer) + return new Precise (result, precision) + } + + add (other) { + if (this.decimals === other.decimals) { + const integerResult = this.integer.add (other.integer) + return new Precise (integerResult, this.decimals) + } else { + const [ smaller, bigger ] = + (this.decimals > other.decimals) ? [ other, this ] : [ this, other ] + const exponent = new BN (bigger.decimals - smaller.decimals) + const normalised = smaller.integer.mul (new BN (this.base).pow (exponent)) + const result = normalised.add (bigger.integer) + return new Precise (result, bigger.decimals) + } + } + + sub (other) { + const negative = new Precise (other.integer.neg (), other.decimals) + return this.add (negative) + } + + reduce () { + const zero = new BN (0) + if (this.integer.eq (zero)) { + this.decimals = 0 + return this + } + const base = new BN (this.base) + let divmod = this.integer.divmod (base) + while (divmod.mod.eq (zero)) { + this.integer = divmod.div + this.decimals-- + divmod = this.integer.divmod (base) + } + return this + } + + toString () { + const sign = this.integer.negative ? '-' : '' + const integerArray = Array.from (this.integer.abs ().toString (this.base).padStart (this.decimals, '0')) + const index = integerArray.length - this.decimals + let item + if (index === 0) { + // if we are adding to the front + item = '0.' + } else if (this.decimals < 0) { + item = '0'.repeat (-this.decimals) + } else if (this.decimals === 0) { + item = '' + } else { + item = '.' + } + integerArray.splice (index, 0, item) + return sign + integerArray.join ('') + } + + static stringMul (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).mul (new Precise (string2)).toString () + } + + static stringDiv (string1, string2, precision = 18) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).div (new Precise (string2), precision).toString () + } + + static stringAdd (string1, string2) { + if ((string1 === undefined) && (string2 === undefined)) { + return undefined + } + if (string1 === undefined) { + return string2 + } else if (string2 === undefined) { + return string1 + } + return (new Precise (string1)).add (new Precise (string2)).toString () + } + + static stringSub (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).sub (new Precise (string2)).toString () + } +} + +module.exports = Precise; + +},{"../static_dependencies/BN/bn":123}],8:[function(require,module,exports){ 'use strict'; const errorHierarchy = { @@ -5074,7 +6623,7 @@ const errorHierarchy = { module.exports = errorHierarchy; -},{}],8:[function(require,module,exports){ +},{}],9:[function(require,module,exports){ 'use strict'; const errorHierarchy = require ('./errorHierarchy.js') @@ -5131,7 +6680,7 @@ module.exports = subclass ( errorHierarchy ) -},{"./errorHierarchy.js":7}],9:[function(require,module,exports){ +},{"./errorHierarchy.js":8}],10:[function(require,module,exports){ 'use strict'; /* ------------------------------------------------------------------------ */ @@ -5161,7 +6710,7 @@ module.exports = unCamelCasePropertyNames (Object.assign ({} /* ------------------------------------------------------------------------ */ -},{"./functions/crypto":10,"./functions/encode":11,"./functions/generic":12,"./functions/misc":13,"./functions/number":14,"./functions/platform":15,"./functions/string":16,"./functions/throttle":17,"./functions/time":18,"./functions/type":19}],10:[function(require,module,exports){ +},{"./functions/crypto":11,"./functions/encode":12,"./functions/generic":13,"./functions/misc":14,"./functions/number":15,"./functions/platform":16,"./functions/string":17,"./functions/throttle":18,"./functions/time":19,"./functions/type":20}],11:[function(require,module,exports){ 'use strict' /* ------------------------------------------------------------------------ */ @@ -5321,7 +6870,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"../../static_dependencies/BN/bn.js":126,"../../static_dependencies/crypto-js/crypto-js":127,"./../../static_dependencies/elliptic/lib/elliptic":128,"./../../static_dependencies/node-rsa/NodeRSA":146,"./../errors":8,"./encode":11,"./string":16}],11:[function(require,module,exports){ +},{"../../static_dependencies/BN/bn.js":123,"../../static_dependencies/crypto-js/crypto-js":124,"./../../static_dependencies/elliptic/lib/elliptic":125,"./../../static_dependencies/node-rsa/NodeRSA":143,"./../errors":9,"./encode":12,"./string":17}],12:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -5343,7 +6892,6 @@ let base58Encoder = null module.exports = { json: (data, params = undefined) => JSON.stringify (data) - , unjson: JSON.parse , isJsonEncodedObject: object => ( (typeof object === 'string') && @@ -5441,7 +6989,7 @@ module.exports['byteArrayToWordArray'] = byteArrayToWordArray /* ------------------------------------------------------------------------ */ -},{"../../static_dependencies/BN/bn":126,"../../static_dependencies/crypto-js/crypto-js":127,"../../static_dependencies/qs/index":162}],12:[function(require,module,exports){ +},{"../../static_dependencies/BN/bn":123,"../../static_dependencies/crypto-js/crypto-js":124,"../../static_dependencies/qs/index":159}],13:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -5679,7 +7227,7 @@ module.exports = { } -},{"./type":19}],13:[function(require,module,exports){ +},{"./type":20}],14:[function(require,module,exports){ 'use strict'; const { ROUND_UP, ROUND_DOWN } = require ('./number') @@ -5819,7 +7367,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"../errors":8,"./number":14}],14:[function(require,module,exports){ +},{"../errors":9,"./number":15}],15:[function(require,module,exports){ 'use strict' /* ------------------------------------------------------------------------ @@ -6160,7 +7708,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{}],15:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ (function (process){ "use strict"; @@ -6201,7 +7749,7 @@ module.exports = { defaultFetch, } }).call(this,require('_process')) -},{"../../static_dependencies/fetch-ponyfill/fetch-node":144,"_process":210}],16:[function(require,module,exports){ +},{"../../static_dependencies/fetch-ponyfill/fetch-node":141,"_process":206}],17:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -6221,7 +7769,7 @@ module.exports = { , strip: s => s.replace(/^\s+|\s+$/g, '') } -},{}],17:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -6287,7 +7835,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"./time":18}],18:[function(require,module,exports){ +},{"./time":19}],19:[function(require,module,exports){ 'use strict'; /* ------------------------------------------------------------------------ */ @@ -6491,7 +8039,7 @@ module.exports = /* ------------------------------------------------------------------------ */ -},{}],19:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -6559,7 +8107,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{}],20:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -6593,13 +8141,14 @@ module.exports = class bequant extends hitbtc { } }; -},{"./hitbtc":93}],21:[function(require,module,exports){ +},{"./hitbtc":91}],22:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AccountSuspended, ArgumentsRequired, AuthenticationError, DDoSProtection, ExchangeNotAvailable, InvalidOrder, OrderNotFound, PermissionDenied, InsufficientFunds, BadSymbol, RateLimitExceeded, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -6825,9 +8374,9 @@ module.exports = class bibox extends Exchange { const quote = this.safeCurrencyCode (quoteId); symbol = base + '/' + quote; } - const last = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); - const baseVolume = this.safeFloat2 (ticker, 'vol', 'vol24H'); + const last = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); + const baseVolume = this.safeNumber2 (ticker, 'vol', 'vol24H'); let open = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; @@ -6841,11 +8390,11 @@ module.exports = class bibox extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -6856,7 +8405,7 @@ module.exports = class bibox extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': baseVolume, - 'quoteVolume': this.safeFloat (ticker, 'amount'), + 'quoteVolume': this.safeNumber (ticker, 'amount'), 'info': ticker, }; } @@ -6872,17 +8421,6 @@ module.exports = class bibox extends Exchange { return this.parseTicker (response['result'], market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - const ticker = this.parseTicker (rawTickers[i]); - if ((symbols === undefined) || (this.inArray (ticker['symbol'], symbols))) { - tickers.push (ticker); - } - } - return tickers; - } - async fetchTickers (symbols = undefined, params = {}) { const request = { 'cmd': 'marketAll', @@ -6915,7 +8453,7 @@ module.exports = class bibox extends Exchange { symbol = market['symbol']; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = this.safeString (trade, 'fee_symbol'); if (feeCurrency !== undefined) { if (feeCurrency in this.currencies_by_id) { @@ -6925,12 +8463,11 @@ module.exports = class bibox extends Exchange { } } const feeRate = undefined; // todo: deduce from market if market is defined - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if (feeCost !== undefined) { fee = { 'cost': -feeCost, @@ -6981,7 +8518,7 @@ module.exports = class bibox extends Exchange { request['size'] = limit; // default = 200 } const response = await this.publicGetMdata (this.extend (request, params)); - return this.parseOrderBook (response['result'], this.safeFloat (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); + return this.parseOrderBook (response['result'], this.safeNumber (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); } parseOHLCV (ohlcv, market = undefined) { @@ -6997,11 +8534,11 @@ module.exports = class bibox extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -7093,7 +8630,7 @@ module.exports = class bibox extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw_min'), + 'min': this.safeNumber (currency, 'withdraw_min'), 'max': undefined, }, }, @@ -7225,19 +8762,17 @@ module.exports = class bibox extends Exchange { code = this.currencies_by_id[code]['code']; } const account = this.account (); - let balance = indexed[id]; + const balance = indexed[id]; if (typeof balance === 'string') { - balance = parseFloat (balance); account['free'] = balance; - account['used'] = 0.0; account['total'] = balance; } else { - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -7328,8 +8863,8 @@ module.exports = class bibox extends Exchange { let tag = this.safeString (transaction, 'addr_remark'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'fee'); if (type === 'deposit') { feeCost = 0; tag = undefined; @@ -7437,26 +8972,19 @@ module.exports = class bibox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const type = (order['order_type'] === 1) ? 'market' : 'limit'; - const timestamp = order['createdAt']; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'deal_price'); - const filled = this.safeFloat (order, 'deal_amount'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat2 (order, 'deal_money', 'money'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - cost = price * filled; - } - } - const side = (order['order_side'] === 1) ? 'buy' : 'sell'; + const rawType = this.safeString (order, 'order_type'); + const type = (rawType === '1') ? 'market' : 'limit'; + const timestamp = this.safeInteger (order, 'createdAt'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'deal_price'); + const filled = this.safeNumber (order, 'deal_amount'); + const amount = this.safeNumber (order, 'amount'); + const cost = this.safeNumber2 (order, 'deal_money', 'money'); + const rawSide = this.safeString (order, 'order_side'); + const side = (rawSide === '1') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -7464,8 +8992,7 @@ module.exports = class bibox extends Exchange { 'currency': undefined, }; } - cost = cost ? cost : (parseFloat (price) * filled); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -7483,11 +9010,11 @@ module.exports = class bibox extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -7655,7 +9182,7 @@ module.exports = class bibox extends Exchange { }; const response = await this.privatePostTransfer (request); info[code] = response; - withdrawFees[code] = this.safeFloat (response['result'], 'withdraw_fee'); + withdrawFees[code] = this.safeNumber (response['result'], 'withdraw_fee'); } return { 'info': info, @@ -7725,13 +9252,14 @@ module.exports = class bibox extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],22:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],23:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, OrderNotFound, InsufficientFunds, PermissionDenied, BadRequest, RateLimitExceeded, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -7988,28 +9516,28 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (ticker, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = undefined; - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', {}); const ask = this.safeValue (ticker, 'ask', {}); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 'price'), - 'bidVolume': this.safeFloat (bid, 'quantity'), - 'ask': this.safeFloat (ask, 'price'), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 'price'), + 'bidVolume': this.safeNumber (bid, 'quantity'), + 'ask': this.safeNumber (ask, 'price'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, 'last': close, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'daily_change'), + 'change': this.safeNumber (ticker, 'daily_change'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -8174,16 +9702,13 @@ module.exports = class bigone extends Exchange { // } // const timestamp = this.parse8601 (this.safeString2 (trade, 'created_at', 'inserted_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } let side = this.safeString (trade, 'side'); const takerSide = this.safeString (trade, 'taker_side'); let takerOrMaker = undefined; @@ -8257,8 +9782,8 @@ module.exports = class bigone extends Exchange { takerCurrencyCode = market['quote']; } } - const makerFeeCost = this.safeFloat (trade, 'maker_fee'); - const takerFeeCost = this.safeFloat (trade, 'taker_fee'); + const makerFeeCost = this.safeNumber (trade, 'maker_fee'); + const takerFeeCost = this.safeNumber (trade, 'taker_fee'); if (makerFeeCost !== undefined) { if (takerFeeCost !== undefined) { result['fees'] = [ @@ -8321,11 +9846,11 @@ module.exports = class bigone extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -8396,11 +9921,11 @@ module.exports = class bigone extends Exchange { const symbol = this.safeString (balance, 'asset_symbol'); const code = this.safeCurrencyCode (symbol); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -8422,13 +9947,9 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (order, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (amount !== undefined && filled !== undefined) { - remaining = Math.max (0, amount - filled); - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); const status = this.parseOrderStatus (this.safeString (order, 'state')); let side = this.safeString (order, 'side'); if (side === 'BID') { @@ -8436,15 +9957,9 @@ module.exports = class bigone extends Exchange { } else { side = 'sell'; } - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'updated_at')); - const average = this.safeFloat (order, 'avg_deal_price'); - return { + const average = this.safeNumber (order, 'avg_deal_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -8459,14 +9974,14 @@ module.exports = class bigone extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -8490,7 +10005,7 @@ module.exports = class bigone extends Exchange { const isStopLimit = (uppercaseType === 'STOP_LIMIT'); const isStopMarket = (uppercaseType === 'STOP_MARKET'); if (isStopLimit || isStopMarket) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price parameter'); } @@ -8829,7 +10344,7 @@ module.exports = class bigone extends Exchange { const currencyId = this.safeString (transaction, 'asset_symbol'); const code = this.safeCurrencyCode (currencyId); const id = this.safeInteger (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const timestamp = this.parse8601 (this.safeString (transaction, 'inserted_at')); const updated = this.parse8601 (this.safeString2 (transaction, 'updated_at', 'completed_at')); @@ -9000,14 +10515,15 @@ module.exports = class bigone extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],23:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],24:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, RateLimitExceeded, PermissionDenied, NotSupported, BadRequest, BadSymbol, AccountSuspended, OrderImmediatelyFillable } = require ('./base/errors'); -const { ROUND, TRUNCATE } = require ('./base/functions/number'); +const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -9050,6 +10566,8 @@ module.exports = class binance extends Exchange { 'fetchTransactions': false, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, + 'fetchTransfers': true, }, 'timeframes': { '1m': '1m', @@ -9198,6 +10716,26 @@ module.exports = class binance extends Exchange { 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/recentRecord', 'apiReferral/kickback/historicalRecord', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccount', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/info', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/recentRecord', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/status', + 'broker/subAccount/depositHist', + 'broker/subAccount/spotSummary', + 'broker/subAccount/marginSummary', + 'broker/subAccount/futuresSummary', + 'broker/rebate/futures/recentRecord', + 'broker/subAccountApi/ipRestriction', + 'broker/universalTransfer', + // v2 not supported yet + // GET /sapi/v2/broker/subAccount/futuresSummary ], 'post': [ 'asset/dust', @@ -9237,11 +10775,30 @@ module.exports = class binance extends Exchange { // leveraged token endpoints 'blvt/subscribe', 'blvt/redeem', - // broker api + // brokerage API 'apiReferral/customization', 'apiReferral/userCustomization', 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/historicalRecord', + 'broker/subAccount', + 'broker/subAccount/margin', + 'broker/subAccount/futures', + 'broker/subAccountApi', + 'broker/subAccountApi/permission', + 'broker/subAccountApi/commission', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/spot', + 'broker/subAccount/bnbBurn/marginInterest', + 'broker/subAccount/blvt', + 'broker/subAccountApi/ipRestriction', + 'broker/subAccountApi/ipRestriction/ipList', + 'broker/universalTransfer', + 'broker/subAccountApi/permission/universalTransfer', + 'broker/subAccountApi/permission/vanillaOptions', ], 'put': [ 'userDataStream', @@ -9252,6 +10809,9 @@ module.exports = class binance extends Exchange { 'margin/order', 'userDataStream', 'userDataStream/isolated', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccountApi/ipRestriction/ipList', ], }, 'wapi': { @@ -9388,6 +10948,8 @@ module.exports = class binance extends Exchange { 'positionSide/dual', 'userTrades', 'income', + 'commissionRate', + 'apiTradingStatus', // broker endpoints 'apiReferral/ifNewUser', 'apiReferral/customization', @@ -9477,6 +11039,7 @@ module.exports = class binance extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.001, @@ -9501,7 +11064,7 @@ module.exports = class binance extends Exchange { 'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision 'newOrderRespType': { 'market': 'FULL', // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills - 'limit': 'RESULT', // we change it from 'ACK' by default to 'RESULT' + 'limit': 'FULL', // we change it from 'ACK' by default to 'FULL' (returns immediately if limit is not hit) }, 'quoteOrderQty': true, // whether market orders support amounts in quote currency 'broker': { @@ -9510,6 +11073,25 @@ module.exports = class binance extends Exchange { 'future': 'x-xcKtGhcu', 'delivery': 'x-xcKtGhcu', }, + 'fetchPositions': { + 'future': 'fapiPrivateV2GetAccount', // 'fapiPrivateGetPositionRisk' + 'delivery': 'dapiPrivateGetAccount', // 'dapiPrivateGetPositionRisk' + }, + 'accountsByType': { + 'main': 'MAIN', + 'spot': 'MAIN', + 'margin': 'MARGIN', + 'future': 'UMFUTURE', + 'delivery': 'CMFUTURE', + 'mining': 'MINING', + }, + 'typesByAccount': { + 'MAIN': 'spot', + 'MARGIN': 'margin', + 'UMFUTURE': 'future', + 'CMFUTURE': 'delivery', + 'MINING': 'mining', + }, }, // https://binance-docs.github.io/apidocs/spot/en/#error-codes-2 'exceptions': { @@ -9567,6 +11149,8 @@ module.exports = class binance extends Exchange { '-3010': ExchangeError, // {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."} '-3022': AccountSuspended, // You account's trading is banned. '-4028': BadRequest, // {"code":-4028,"msg":"Leverage 100 is not valid"} + '-3020': InsufficientFunds, // {"code":-3020,"msg":"Transfer out amount exceeds max amount."} + '-3041': InsufficientFunds, // {"code":-3041,"msg":"Balance is not enough"} '-5013': InsufficientFunds, // Asset transfer failed: insufficient balance" }, }); @@ -9709,13 +11293,14 @@ module.exports = class binance extends Exchange { let fee = undefined; for (let j = 0; j < networkList.length; j++) { const networkItem = networkList[j]; - const name = this.safeString (networkItem, 'name'); - const withdrawFee = this.safeFloat (networkItem, 'withdrawFee'); + const network = this.safeString (networkItem, 'network'); + // const name = this.safeString (networkItem, 'name'); + const withdrawFee = this.safeNumber (networkItem, 'withdrawFee'); const depositEnable = this.safeValue (networkItem, 'depositEnable'); const withdrawEnable = this.safeValue (networkItem, 'withdrawEnable'); isDepositEnabled = isDepositEnabled || depositEnable; isWithdrawEnabled = isWithdrawEnabled || withdrawEnable; - fees[name] = withdrawFee; + fees[network] = withdrawFee; const isDefault = this.safeValue (networkItem, 'isDefault'); if (isDefault || fee === undefined) { fee = withdrawFee; @@ -9901,7 +11486,7 @@ module.exports = class binance extends Exchange { if (this.options['adjustForTimeDifference']) { await this.loadTimeDifference (); } - const markets = this.safeValue (response, 'symbols'); + const markets = this.safeValue (response, 'symbols', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -9966,10 +11551,10 @@ module.exports = class binance extends Exchange { // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } @@ -9980,47 +11565,26 @@ module.exports = class binance extends Exchange { const stepSize = this.safeString (filter, 'stepSize'); entry['precision']['amount'] = this.precisionFromString (stepSize); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat2 (filter, 'minNotional', 'notional'); + entry['limits']['cost']['min'] = this.safeNumber2 (filter, 'minNotional', 'notional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot'); @@ -10191,8 +11755,8 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -10205,13 +11769,13 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['used'] = this.safeFloat (balance, 'initialMargin'); - account['total'] = this.safeFloat2 (balance, 'marginBalance', 'balance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['used'] = this.safeString (balance, 'initialMargin'); + account['total'] = this.safeString2 (balance, 'marginBalance', 'balance'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -10264,36 +11828,36 @@ module.exports = class binance extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'openPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'openPrice'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } async fetchStatus (params = {}) { const response = await this.wapiGetSystemStatus (params); - let status = this.safeValue (response, 'status'); + let status = this.safeString (response, 'status'); if (status !== undefined) { - status = (status === 0) ? 'ok' : 'maintenance'; + status = (status === '0') ? 'ok' : 'maintenance'; this.status = this.extend (this.status, { 'status': status, 'updated': this.milliseconds (), @@ -10322,14 +11886,6 @@ module.exports = class binance extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot'); @@ -10384,11 +11940,11 @@ module.exports = class binance extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -10519,8 +12075,11 @@ module.exports = class binance extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -10538,7 +12097,7 @@ module.exports = class binance extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -10551,10 +12110,6 @@ module.exports = class binance extends Exchange { } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } return { 'info': trade, 'timestamp': timestamp, @@ -10673,7 +12228,7 @@ module.exports = class binance extends Exchange { parseOrder (order, market = undefined) { // - // spot + // spot // // { // "symbol": "LTCBTC", @@ -10694,7 +12249,7 @@ module.exports = class binance extends Exchange { // "isWorking": true // } // - // futures + // futures // // { // "symbol": "BTCUSDT", @@ -10712,6 +12267,33 @@ module.exports = class binance extends Exchange { // "updateTime": 1499827319559 // } // + // createOrder with { "newOrderRespType": "FULL" } + // + // { + // "symbol": "BTCUSDT", + // "orderId": 5403233939, + // "orderListId": -1, + // "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e", + // "transactTime": 1617151923742, + // "price": "0.00000000", + // "origQty": "0.00050000", + // "executedQty": "0.00050000", + // "cummulativeQuoteQty": "29.47081500", + // "status": "FILLED", + // "timeInForce": "GTC", + // "type": "MARKET", + // "side": "BUY", + // "fills": [ + // { + // "price": "58941.63000000", + // "qty": "0.00050000", + // "commission": "0.00007050", + // "commissionAsset": "BNB", + // "tradeId": 737466631 + // } + // ] + // } + // const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -10721,80 +12303,26 @@ module.exports = class binance extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); // - Spot/Margin market: cummulativeQuoteQty // - Futures market: cumQuote. // Note this is not the actual cost, since Binance futures uses leverage to calculate margins. - let cost = this.safeFloat2 (order, 'cummulativeQuoteQty', 'cumQuote'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const cost = this.safeNumber2 (order, 'cummulativeQuoteQty', 'cumQuote'); const id = this.safeString (order, 'orderId'); let type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - if (this.options['parseOrderToPrecision']) { - price = parseFloat (this.priceToPrecision (symbol, price)); - } - } - } - } - } else if (type === 'limit_maker') { + if (type === 'limit_maker') { type = 'limit'; } const side = this.safeStringLower (order, 'side'); - let fee = undefined; - let trades = undefined; - const fills = this.safeValue (order, 'fills'); - if (fills !== undefined) { - trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - if (this.options['parseOrderToPrecision']) { - average = parseFloat (this.priceToPrecision (symbol, average)); - } - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const fills = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (fills, market); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = (type === 'limit_maker') || (timeInForce === 'GTX'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -10810,13 +12338,13 @@ module.exports = class binance extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -10863,8 +12391,11 @@ module.exports = class binance extends Exchange { } else { request['newClientOrderId'] = clientOrderId; } - if (market['spot']) { + if ((orderType === 'spot') || (orderType === 'margin')) { request['newOrderRespType'] = this.safeValue (this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills + } else { + // delivery and future + request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK" } // additional required fields depending on the order type let timeInForceIsRequired = false; @@ -10894,7 +12425,7 @@ module.exports = class binance extends Exchange { if (uppercaseType === 'MARKET') { const quoteOrderQty = this.safeValue (this.options, 'quoteOrderQty', false); if (quoteOrderQty) { - const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty'); + const quoteOrderQty = this.safeNumber (params, 'quoteOrderQty'); const precision = market['precision']['price']; if (quoteOrderQty !== undefined) { request['quoteOrderQty'] = this.decimalToPrecision (quoteOrderQty, TRUNCATE, precision, this.precisionMode); @@ -10914,7 +12445,7 @@ module.exports = class binance extends Exchange { } else if ((uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT')) { stopPriceIsRequired = true; quantityIsRequired = true; - if (market['future']) { + if (market['future'] || market['delivery']) { priceIsRequired = true; } } else if ((uppercaseType === 'STOP_LOSS_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) { @@ -10937,7 +12468,7 @@ module.exports = class binance extends Exchange { stopPriceIsRequired = true; } else if (uppercaseType === 'TRAILING_STOP_MARKET') { quantityIsRequired = true; - const callbackRate = this.safeFloat (params, 'callbackRate'); + const callbackRate = this.safeNumber (params, 'callbackRate'); if (callbackRate === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a callbackRate extra param for a ' + type + ' order'); } @@ -10955,7 +12486,7 @@ module.exports = class binance extends Exchange { request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -11171,10 +12702,15 @@ module.exports = class binance extends Exchange { } } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.fetchBalance (params); - const info = this.safeValue (response, 'info', {}); + const defaultType = this.safeString (this.options, 'defaultType', 'future'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + const options = this.safeValue (this.options, 'fetchPositions', {}); + const defaultMethod = (type === 'delivery') ? 'dapiPrivateGetAccount' : 'fapiPrivateV2GetAccount'; + const method = this.safeString (options, type, defaultMethod); + const response = await this[method] (params); // // futures, delivery // @@ -11217,9 +12753,44 @@ module.exports = class binance extends Exchange { // ] // } // - const positions = this.safeValue2 (info, 'positions', 'userAssets', []); - // todo unify parsePosition/parsePositions - return positions; + // fapiPrivateGetPositionRisk, dapiPrivateGetPositionRisk + // + // [ + // { + // symbol: 'XRPUSD_210625', + // positionAmt: '0', + // entryPrice: '0.00000000', + // markPrice: '0.00000000', + // unRealizedProfit: '0.00000000', + // liquidationPrice: '0', + // leverage: '20', + // maxQty: '500000', + // marginType: 'cross', + // isolatedMargin: '0.00000000', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0', + // isolatedWallet: '0' + // }, + // { + // symbol: 'BTCUSD_210326', + // positionAmt: '1', + // entryPrice: '60665.79999885', + // markPrice: '60696.76856843', + // unRealizedProfit: '0.00000084', + // liquidationPrice: '58034.68208092', + // leverage: '20', + // maxQty: '50', + // marginType: 'isolated', + // isolatedMargin: '0.00008345', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0.00164753', + // isolatedWallet: '0.00008261' + // }, + // ] + // + return this.safeValue (response, 'positions', response); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -11357,7 +12928,7 @@ module.exports = class binance extends Exchange { // const fee = { 'currency': earnedCurrency, - 'cost': this.safeFloat (trade, 'serviceChargeAmount'), + 'cost': this.safeNumber (trade, 'serviceChargeAmount'), }; let symbol = undefined; let amount = undefined; @@ -11365,13 +12936,13 @@ module.exports = class binance extends Exchange { let side = undefined; if (tradedCurrencyIsQuote) { symbol = applicantSymbol; - amount = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); - cost = this.safeFloat (trade, 'amount'); + amount = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); + cost = this.safeNumber (trade, 'amount'); side = 'buy'; } else { symbol = tradedCurrency + '/' + earnedCurrency; - amount = this.safeFloat (trade, 'amount'); - cost = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); + amount = this.safeNumber (trade, 'amount'); + cost = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); side = 'sell'; } let price = undefined; @@ -11544,8 +13115,8 @@ module.exports = class binance extends Exchange { } } const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'transactionFee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'transactionFee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -11572,6 +13143,151 @@ module.exports = class binance extends Exchange { }; } + parseTransferStatus (status) { + const statuses = { + 'CONFIRMED': 'ok', + }; + return this.safeString (statuses, status, status); + } + + parseTransfer (transfer, currency = undefined) { + // + // transfer + // + // { + // "tranId":13526853623 + // } + // + // fetchTransfers + // + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // } + // + const id = this.safeString (transfer, 'tranId'); + const currencyId = this.safeString (transfer, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const amount = this.safeNumber (transfer, 'amount'); + const type = this.safeString (transfer, 'type'); + let fromAccount = undefined; + let toAccount = undefined; + const typesByAccount = this.safeValue (this.options, 'typesByAccount', {}); + if (type !== undefined) { + const parts = type.split ('_'); + fromAccount = this.safeValue (parts, 0); + toAccount = this.safeValue (parts, 1); + fromAccount = this.safeString (typesByAccount, fromAccount, fromAccount); + toAccount = this.safeString (typesByAccount, toAccount, toAccount); + } + const timestamp = this.safeInteger (transfer, 'timestamp'); + const status = this.parseTransferStatus (this.safeString (transfer, 'status')); + return { + 'info': transfer, + 'id': id, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'currency': code, + 'amount': amount, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': status, + }; + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount, fromAccount); + const toId = this.safeString (accountsByType, toAccount, toAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'asset': currency['id'], + 'amount': this.currencyToPrecision (code, amount), + 'type': type, + }; + const response = await this.sapiPostAssetTransfer (this.extend (request, params)); + // + // { + // "tranId":13526853623 + // } + // + const transfer = this.parseTransfer (response, currency); + return this.extend (transfer, { + 'amount': amount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + }); + } + + async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const defaultType = this.safeString2 (this.options, 'fetchTransfers', 'defaultType', 'spot'); + const fromAccount = this.safeString (params, 'fromAccount', defaultType); + const defaultTo = (fromAccount === 'future') ? 'spot' : 'future'; + const toAccount = this.safeString (params, 'toAccount', defaultTo); + let type = this.safeString (params, 'type'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + if (type === undefined) { + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount parameter must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount parameter must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'type': type, + }; + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['size'] = limit; + } + const response = await this.sapiGetAssetTransfer (this.extend (request, params)); + // + // { + // total: 3, + // rows: [ + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // }, + // ] + // } + // + const rows = this.safeValue (response, 'rows', []); + return this.parseTransfers (rows, currency, since, limit); + } + async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -11634,7 +13350,7 @@ module.exports = class binance extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (detail[id], 'withdrawFee'); + withdrawFees[code] = this.safeNumber (detail[id], 'withdrawFee'); } return { 'withdraw': withdrawFees, @@ -11681,8 +13397,8 @@ module.exports = class binance extends Exchange { return { 'info': fee, 'symbol': symbol, - 'maker': this.safeFloat (fee, 'maker'), - 'taker': this.safeFloat (fee, 'taker'), + 'maker': this.safeNumber (fee, 'maker'), + 'taker': this.safeNumber (fee, 'taker'), }; } @@ -11744,7 +13460,6 @@ module.exports = class binance extends Exchange { if (api === 'wapi') { url += '.html'; } - const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); if (path === 'historicalTrades') { if (this.apiKey) { headers = { @@ -11753,19 +13468,22 @@ module.exports = class binance extends Exchange { } else { throw new AuthenticationError (this.id + ' historicalTrades endpoint requires `apiKey` credential'); } - } else if (userDataStream) { + } + const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); + if (userDataStream) { if (this.apiKey) { // v1 special case for userDataStream - body = this.urlencode (params); headers = { 'X-MBX-APIKEY': this.apiKey, 'Content-Type': 'application/x-www-form-urlencoded', }; + if (method !== 'GET') { + body = this.urlencode (params); + } } else { throw new AuthenticationError (this.id + ' userDataStream endpoint requires `apiKey` credential'); } - } - if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { + } else if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { this.checkRequiredCredentials (); let query = undefined; const recvWindow = this.safeInteger (this.options, 'recvWindow', 5000); @@ -11797,13 +13515,8 @@ module.exports = class binance extends Exchange { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } } else { - // userDataStream endpoints are public, but POST, PUT, DELETE - // therefore they don't accept URL query arguments - // https://github.com/ccxt/ccxt/issues/5224 - if (!userDataStream) { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } + if (Object.keys (params).length) { + url += '?' + this.urlencode (params); } } return { 'url': url, 'method': method, 'body': body, 'headers': headers }; @@ -11885,7 +13598,7 @@ module.exports = class binance extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],24:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],25:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -11937,13 +13650,14 @@ module.exports = class binanceus extends binance { }; -},{"./binance.js":23}],25:[function(require,module,exports){ +},{"./binance.js":24}],26:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, InvalidNonce, AuthenticationError, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -12095,12 +13809,12 @@ module.exports = class bit2c extends Exchange { const currencyId = this.currencyId (code); const uppercase = currencyId.toUpperCase (); if (uppercase in balance) { - account['free'] = this.safeFloat (balance, 'AVAILABLE_' + uppercase); - account['total'] = this.safeFloat (balance, uppercase); + account['free'] = this.safeString (balance, 'AVAILABLE_' + uppercase); + account['total'] = this.safeString (balance, uppercase); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -12119,22 +13833,22 @@ module.exports = class bit2c extends Exchange { }; const ticker = await this.publicGetExchangesPairTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const averagePrice = this.safeFloat (ticker, 'av'); - const baseVolume = this.safeFloat (ticker, 'a'); + const averagePrice = this.safeNumber (ticker, 'av'); + const baseVolume = this.safeNumber (ticker, 'a'); let quoteVolume = undefined; if (baseVolume !== undefined && averagePrice !== undefined) { quoteVolume = baseVolume * averagePrice; } - const last = this.safeFloat (ticker, 'll'); + const last = this.safeNumber (ticker, 'll'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'h'), + 'bid': this.safeNumber (ticker, 'h'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'l'), + 'ask': this.safeNumber (ticker, 'l'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -12216,14 +13930,8 @@ module.exports = class bit2c extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -12236,7 +13944,7 @@ module.exports = class bit2c extends Exchange { } const id = this.safeString (order, 'id'); const status = this.safeString (order, 'status'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -12253,12 +13961,12 @@ module.exports = class bit2c extends Exchange { 'amount': amount, 'filled': undefined, 'remaining': undefined, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -12284,16 +13992,16 @@ module.exports = class bit2c extends Exchange { parseTrade (trade, market = undefined) { let timestamp = undefined; let id = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let orderId = undefined; let feeCost = undefined; let side = undefined; const reference = this.safeString (trade, 'reference'); if (reference !== undefined) { timestamp = this.safeTimestamp (trade, 'ticks'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'firstAmount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'firstAmount'); const reference_parts = reference.split ('|'); // reference contains 'pair|orderId|tradeId' if (market === undefined) { const marketId = this.safeString (trade, 'pair'); @@ -12311,12 +14019,12 @@ module.exports = class bit2c extends Exchange { } else if (side === 1) { side = 'sell'; } - feeCost = this.safeFloat (trade, 'feeAmount'); + feeCost = this.safeNumber (trade, 'feeAmount'); } else { timestamp = this.safeTimestamp (trade, 'date'); id = this.safeString (trade, 'tid'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'amount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'amount'); side = this.safeValue (trade, 'isBid'); if (side !== undefined) { if (side) { @@ -12330,6 +14038,9 @@ module.exports = class bit2c extends Exchange { if (market !== undefined) { symbol = market['symbol']; } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -12342,7 +14053,7 @@ module.exports = class bit2c extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': { 'cost': feeCost, 'currency': 'NIS', @@ -12398,13 +14109,14 @@ module.exports = class bit2c extends Exchange { }; -},{"./base/Exchange":6,"./base/errors":8}],26:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],27:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -12479,21 +14191,23 @@ module.exports = class bitbank extends Exchange { }, }, 'markets': { + 'BAT/JPY': { 'id': 'bat_jpy', 'symbol': 'BAT/JPY', 'base': 'BAT', 'quote': 'JPY', 'baseId': 'bat', 'quoteId': 'jpy' }, + 'BAT/BTC': { 'id': 'bat_btc', 'symbol': 'BAT/BTC', 'base': 'BAT', 'quote': 'BTC', 'baseId': 'bat', 'quoteId': 'btc' }, 'BCH/BTC': { 'id': 'bcc_btc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'baseId': 'bcc', 'quoteId': 'btc' }, 'BCH/JPY': { 'id': 'bcc_jpy', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bcc', 'quoteId': 'jpy' }, + 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, + 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, + 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, + 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, + 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, 'MONA/BTC': { 'id': 'mona_btc', 'symbol': 'MONA/BTC', 'base': 'MONA', 'quote': 'BTC', 'baseId': 'mona', 'quoteId': 'btc' }, 'MONA/JPY': { 'id': 'mona_jpy', 'symbol': 'MONA/JPY', 'base': 'MONA', 'quote': 'JPY', 'baseId': 'mona', 'quoteId': 'jpy' }, 'QTUM/BTC': { 'id': 'qtum_btc', 'symbol': 'QTUM/BTC', 'base': 'QTUM', 'quote': 'BTC', 'baseId': 'qtum', 'quoteId': 'btc' }, 'QTUM/JPY': { 'id': 'qtum_jpy', 'symbol': 'QTUM/JPY', 'base': 'QTUM', 'quote': 'JPY', 'baseId': 'qtum', 'quoteId': 'jpy' }, - 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, - 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, - 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, - 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, - 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, - 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, - 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, - 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, 'XLM/BTC': { 'id': 'xlm_btc', 'symbol': 'XLM/BTC', 'base': 'XLM', 'quote': 'BTC', 'baseId': 'xlm', 'quoteId': 'btc' }, + 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, + 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, + 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, }, 'fees': { 'trading': { @@ -12542,16 +14256,16 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -12561,7 +14275,7 @@ module.exports = class bitbank extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -12597,18 +14311,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; feeCurrency = market['quote']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'transaction_id', 'trade_id'); const takerOrMaker = this.safeString (trade, 'maker_taker'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee_amount_quote'); + const feeCost = this.safeNumber (trade, 'fee_amount_quote'); if (feeCost !== undefined) { fee = { 'currency': feeCurrency, @@ -12660,11 +14371,11 @@ module.exports = class bitbank extends Exchange { // return [ this.safeInteger (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -12715,14 +14426,13 @@ module.exports = class bitbank extends Exchange { const balance = assets[i]; const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'free_amount'), - 'used': this.safeFloat (balance, 'locked_amount'), - 'total': this.safeFloat (balance, 'onhand_amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'free_amount'); + account['used'] = this.safeString (balance, 'locked_amount'); + account['total'] = this.safeString (balance, 'onhand_amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -12747,21 +14457,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (order, 'ordered_at'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'start_amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const average = this.safeFloat (order, 'average_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'start_amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const average = this.safeNumber (order, 'average_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -12775,7 +14479,7 @@ module.exports = class bitbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, @@ -12783,7 +14487,7 @@ module.exports = class bitbank extends Exchange { 'trades': undefined, 'fee': undefined, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -13026,13 +14730,14 @@ module.exports = class bitbank extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],27:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],28:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -13307,8 +15012,8 @@ module.exports = class bitbay extends Exchange { if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) { fees = this.safeValue (this.fees, 'fiat', {}); } - const maker = this.safeFloat (fees, 'maker'); - const taker = this.safeFloat (fees, 'taker'); + const maker = this.safeNumber (fees, 'maker'); + const taker = this.safeNumber (fees, 'taker'); // todo: check that the limits have ben interpreted correctly // todo: parse the fees page result.push ({ @@ -13324,7 +15029,7 @@ module.exports = class bitbay extends Exchange { 'taker': taker, 'limits': { 'amount': { - 'min': this.safeFloat (first, 'minOffer'), + 'min': this.safeNumber (first, 'minOffer'), 'max': undefined, }, 'price': { @@ -13332,7 +15037,7 @@ module.exports = class bitbay extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (second, 'minOffer'), + 'min': this.safeNumber (second, 'minOffer'), 'max': undefined, }, }, @@ -13372,16 +15077,10 @@ module.exports = class bitbay extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (order, 'time'); - const amount = this.safeFloat (order, 'startAmount'); - const remaining = this.safeFloat (order, 'currentAmount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } + const amount = this.safeNumber (order, 'startAmount'); + const remaining = this.safeNumber (order, 'currentAmount'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'info': order, @@ -13394,16 +15093,16 @@ module.exports = class bitbay extends Exchange { 'timeInForce': undefined, 'postOnly': postOnly, 'side': this.safeStringLower (order, 'offerType'), - 'price': this.safeFloat (order, 'rate'), + 'price': this.safeNumber (order, 'rate'), 'stopPrice': undefined, 'amount': amount, 'cost': undefined, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'average': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -13456,11 +15155,11 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lockedFunds'); - account['free'] = this.safeFloat (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'lockedFunds'); + account['free'] = this.safeString (balance, 'availableFunds'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -13479,22 +15178,22 @@ module.exports = class bitbay extends Exchange { }; const ticker = await this.publicGetIdTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'volume'); - const vwap = this.safeFloat (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max'), + 'low': this.safeNumber (ticker, 'min'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -13503,7 +15202,7 @@ module.exports = class bitbay extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), + 'average': this.safeNumber (ticker, 'average'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -13804,7 +15503,7 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const change = this.safeValue (item, 'change', {}); - let amount = this.safeFloat (change, 'total'); + let amount = this.safeNumber (change, 'total'); let direction = 'in'; if (amount < 0) { direction = 'out'; @@ -13816,9 +15515,9 @@ module.exports = class bitbay extends Exchange { const referenceId = this.safeString (item, 'detailId'); const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const fundsBefore = this.safeValue (item, 'fundsBefore', {}); - const before = this.safeFloat (fundsBefore, 'total'); + const before = this.safeNumber (fundsBefore, 'total'); const fundsAfter = this.safeValue (item, 'fundsAfter', {}); - const after = this.safeFloat (fundsAfter, 'total'); + const after = this.safeNumber (fundsAfter, 'total'); return { 'info': item, 'id': id, @@ -13875,11 +15574,11 @@ module.exports = class bitbay extends Exchange { const first = this.safeValue (ohlcv, 1, {}); return [ this.safeInteger (ohlcv, 0), - this.safeFloat (first, 'o'), - this.safeFloat (first, 'h'), - this.safeFloat (first, 'l'), - this.safeFloat (first, 'c'), - this.safeFloat (first, 'v'), + this.safeNumber (first, 'o'), + this.safeNumber (first, 'h'), + this.safeNumber (first, 'l'), + this.safeNumber (first, 'c'), + this.safeNumber (first, 'v'), ]; } @@ -13962,15 +15661,12 @@ module.exports = class bitbay extends Exchange { if (wasTaker !== undefined) { takerOrMaker = wasTaker ? 'taker' : 'maker'; } - const price = this.safeFloat2 (trade, 'rate', 'r'); - const amount = this.safeFloat2 (trade, 'amount', 'a'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'commissionValue'); + const priceString = this.safeString2 (trade, 'rate', 'r'); + const amountString = this.safeString2 (trade, 'amount', 'a'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'commissionValue'); const marketId = this.safeString (trade, 'market'); market = this.safeMarket (marketId, market, '-'); const symbol = market['symbol']; @@ -14302,7 +15998,7 @@ module.exports = class bitbay extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],28:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],29:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -14338,7 +16034,7 @@ module.exports = class bitcoincom extends hitbtc { } }; -},{"./hitbtc.js":93}],29:[function(require,module,exports){ +},{"./hitbtc.js":91}],30:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -14346,6 +16042,7 @@ module.exports = class bitcoincom extends hitbtc { const Exchange = require ('./base/Exchange'); const { NotSupported, RateLimitExceeded, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, InvalidNonce, BadSymbol } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -14386,6 +16083,7 @@ module.exports = class bitfinex extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': '1m', @@ -14499,6 +16197,7 @@ module.exports = class bitfinex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'maker': 0.1 / 100, @@ -14685,6 +16384,8 @@ module.exports = class bitfinex extends Exchange { 'No summary found.': ExchangeError, // fetchTradingFees (summary) endpoint can give this vague error message 'Cannot evaluate your available balance, please try again': ExchangeNotAvailable, 'Unknown symbol': BadSymbol, + 'Cannot complete transfer. Exchange balance insufficient.': InsufficientFunds, + 'Momentary balance check. Please wait few seconds and try the transfer again.': ExchangeError, }, 'broad': { 'Invalid X-BFX-SIGNATURE': AuthenticationError, @@ -14782,6 +16483,15 @@ module.exports = class bitfinex extends Exchange { 'limit': 'exchange limit', 'market': 'exchange market', }, + 'accountsByType': { + 'spot': 'exchange', + 'margin': 'trading', + 'funding': 'deposit', + 'exchange': 'exchange', + 'trading': 'trading', + 'deposit': 'deposit', + 'derivatives': 'trading', + }, }, }); } @@ -14795,7 +16505,7 @@ module.exports = class bitfinex extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdraw[code] = this.safeFloat (fees, id); + withdraw[code] = this.safeNumber (fees, id); } return { 'info': response, @@ -14831,14 +16541,31 @@ module.exports = class bitfinex extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } async fetchMarkets (params = {}) { const ids = await this.publicGetSymbols (); + // + // [ "btcusd", "ltcusd", "ltcbtc" ] + // const details = await this.publicGetSymbolsDetails (); + // + // [ + // { + // "pair":"btcusd", + // "price_precision":5, + // "initial_margin":"10.0", + // "minimum_margin":"5.0", + // "maximum_order_size":"2000.0", + // "minimum_order_size":"0.0002", + // "expiration":"NA", + // "margin":true + // }, + // ] + // const result = []; for (let i = 0; i < details.length; i++) { const market = details[i]; @@ -14869,8 +16596,8 @@ module.exports = class bitfinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -14881,6 +16608,7 @@ module.exports = class bitfinex extends Exchange { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -14889,6 +16617,8 @@ module.exports = class bitfinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': true, + 'type': 'spot', + 'margin': margin, 'precision': precision, 'limits': limits, 'info': market, @@ -14913,40 +16643,15 @@ module.exports = class bitfinex extends Exchange { return this.decimalToPrecision (price, TRUNCATE, 8, DECIMAL_PLACES); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - const code = market[key]; - const currency = this.safeValue (this.currencies, code); - if (currency !== undefined) { - const precision = this.safeInteger (currency, 'precision'); - if (precision !== undefined) { - cost = parseFloat (this.currencyToPrecision (code, cost)); - } - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); - const types = { - 'exchange': 'exchange', - 'deposit': 'funding', - 'trading': 'margin', - }; - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } const query = this.omit (params, 'type'); const response = await this.privatePostBalances (query); // [ { type: 'deposit', @@ -14962,12 +16667,16 @@ module.exports = class bitfinex extends Exchange { // amount: '0.0005', // available: '0.0005' } ], const result = { 'info': response }; + const isDerivative = requestedType === 'derivatives'; for (let i = 0; i < response.length; i++) { const balance = response[i]; const type = this.safeString (balance, 'type'); - const parsedType = this.safeString (types, type); - if ((parsedType === balanceType) || (type === balanceType)) { - const currencyId = this.safeString (balance, 'currency'); + const currencyId = this.safeStringLower (balance, 'currency', ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { const code = this.safeCurrencyCode (currencyId); // bitfinex had BCH previously, now it's BAB, but the old // BCH symbol is kept for backward-compatibility @@ -14976,13 +16685,80 @@ module.exports = class bitfinex extends Exchange { // https://github.com/ccxt/ccxt/issues/4989 if (!(code in result)) { const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currencyId = this.currencyId (code); + const fromCurrencyId = this.convertDerivativesId (currencyId, fromAccount); + const toCurrencyId = this.convertDerivativesId (currencyId, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'walletfrom': fromId, + 'walletto': toId, + }; + const response = await this.privatePostTransfer (this.extend (request, params)); + // [ + // { + // status: 'success', + // message: '0.0001 Bitcoin transfered from Margin to Exchange' + // } + // ] + const result = this.safeValue (response, 0); + const status = this.safeString (result, 'status'); + const message = this.safeString (result, 'message'); + if (message === undefined) { + throw new ExchangeError (this.id + ' transfer failed'); + } + // [{"status":"error","message":"Momentary balance check. Please wait few seconds and try the transfer again."}] + if (status === 'error') { + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + return { + 'info': response, + 'status': status, + 'amount': requestedAmount, + 'code': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'timestamp': undefined, + 'datetime': undefined, + }; + } + + convertDerivativesId (currencyId, type) { + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if ((type !== 'derivatives' && type !== 'trading' && type !== 'margin') && isDerivativeCode) { + currencyId = currencyId.slice (0, start); + } else if (type === 'derivatives' && !isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + return currencyId; } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -15021,7 +16797,7 @@ module.exports = class bitfinex extends Exchange { } parseTicker (ticker, market = undefined) { - let timestamp = this.safeFloat (ticker, 'timestamp'); + let timestamp = this.safeNumber (ticker, 'timestamp'); if (timestamp !== undefined) { timestamp *= 1000; } @@ -15044,16 +16820,16 @@ module.exports = class bitfinex extends Exchange { } } } - const last = this.safeFloat (ticker, 'last_price'); + const last = this.safeNumber (ticker, 'last_price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -15062,8 +16838,8 @@ module.exports = class bitfinex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'mid'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'mid'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -15071,24 +16847,21 @@ module.exports = class bitfinex extends Exchange { parseTrade (trade, market) { const id = this.safeString (trade, 'tid'); - let timestamp = this.safeFloat (trade, 'timestamp'); + let timestamp = this.safeNumber (trade, 'timestamp'); if (timestamp !== undefined) { timestamp = parseInt (timestamp) * 1000; } const type = undefined; const side = this.safeStringLower (trade, 'type'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; if ('fee_amount' in trade) { - const feeCost = -this.safeFloat (trade, 'fee_amount'); + const feeCost = -this.safeNumber (trade, 'fee_amount'); const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { @@ -15203,6 +16976,30 @@ module.exports = class bitfinex extends Exchange { } parseOrder (order, market = undefined) { + // + // { + // id: 57334010955, + // cid: 1611584840966, + // cid_date: null, + // gid: null, + // symbol: 'ltcbtc', + // exchange: null, + // price: '0.0042125', + // avg_execution_price: '0.0042097', + // side: 'sell', + // type: 'exchange market', + // timestamp: '1611584841.0', + // is_live: false, + // is_cancelled: false, + // is_hidden: 0, + // oco_order: 0, + // was_forced: false, + // original_amount: '0.205176', + // remaining_amount: '0.0', + // executed_amount: '0.205176', + // src: 'web' + // } + // const side = this.safeString (order, 'side'); const open = this.safeValue (order, 'is_live'); const canceled = this.safeValue (order, 'is_cancelled'); @@ -15214,30 +17011,17 @@ module.exports = class bitfinex extends Exchange { } else { status = 'closed'; } - let symbol = undefined; - if (market === undefined) { - const marketId = this.safeStringUpper (order, 'symbol'); - if (marketId !== undefined) { - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } - } - } - if (market !== undefined) { - symbol = market['symbol']; - } - let orderType = order['type']; + const marketId = this.safeStringUpper (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market); + let orderType = this.safeString (order, 'type', ''); const exchange = orderType.indexOf ('exchange ') >= 0; if (exchange) { const parts = order['type'].split (' '); orderType = parts[1]; } - let timestamp = this.safeFloat (order, 'timestamp'); - if (timestamp !== undefined) { - timestamp = parseInt (timestamp) * 1000; - } + const timestamp = this.safeTimestamp (order, 'timestamp'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -15249,17 +17033,17 @@ module.exports = class bitfinex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': side, - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_execution_price'), - 'amount': this.safeFloat (order, 'original_amount'), - 'remaining': this.safeFloat (order, 'remaining_amount'), - 'filled': this.safeFloat (order, 'executed_amount'), + 'average': this.safeNumber (order, 'avg_execution_price'), + 'amount': this.safeNumber (order, 'original_amount'), + 'remaining': this.safeNumber (order, 'remaining_amount'), + 'filled': this.safeNumber (order, 'executed_amount'), 'status': status, 'fee': undefined, 'cost': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -15314,11 +17098,11 @@ module.exports = class bitfinex extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -15466,11 +17250,11 @@ module.exports = class bitfinex extends Exchange { // "timestamp_created": "1561716066.0" // } // - let timestamp = this.safeFloat (transaction, 'timestamp_created'); + let timestamp = this.safeNumber (transaction, 'timestamp_created'); if (timestamp !== undefined) { timestamp = parseInt (timestamp * 1000); } - let updated = this.safeFloat (transaction, 'timestamp'); + let updated = this.safeNumber (transaction, 'timestamp'); if (updated !== undefined) { updated = parseInt (updated * 1000); } @@ -15478,7 +17262,7 @@ module.exports = class bitfinex extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const type = this.safeStringLower (transaction, 'type'); // DEPOSIT or WITHDRAWAL const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -15491,7 +17275,7 @@ module.exports = class bitfinex extends Exchange { 'address': this.safeString (transaction, 'address'), // todo: this is actually the tag for XRP transfers (the address is missing) 'tag': undefined, // refix it properly for the tag from description 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -15545,7 +17329,7 @@ module.exports = class bitfinex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // @@ -15623,7 +17407,7 @@ module.exports = class bitfinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],30:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],31:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -15912,6 +17696,15 @@ module.exports = class bitfinex2 extends bitfinex { 'JPY': 'JPY', 'GBP': 'GBP', }, + // actually the correct names unlike the v1 + // we don't want to extend this with accountsByType in v1 + 'v2AccountsByType': { + 'spot': 'exchange', + 'exchange': 'exchange', + 'funding': 'funding', + 'margin': 'margin', + 'derivatives': 'margin', + }, }, 'exceptions': { 'exact': { @@ -15993,8 +17786,8 @@ module.exports = class bitfinex2 extends bitfinex { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -16005,6 +17798,7 @@ module.exports = class bitfinex2 extends bitfinex { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -16019,6 +17813,7 @@ module.exports = class bitfinex2 extends bitfinex { 'type': type, 'swap': false, 'spot': spot, + 'margin': margin, 'futures': futures, }); } @@ -16131,7 +17926,7 @@ module.exports = class bitfinex2 extends bitfinex { const ids = this.safeValue (response, 0, []); const result = {}; for (let i = 0; i < ids.length; i++) { - let id = ids[i]; + const id = ids[i]; const code = this.safeCurrencyCode (id); const label = this.safeValue (indexed['label'], id, []); const name = this.safeString (label, 1); @@ -16139,13 +17934,14 @@ module.exports = class bitfinex2 extends bitfinex { const type = this.safeString (pool, 1); const feeValues = this.safeValue (indexed['fees'], id, []); const fees = this.safeValue (feeValues, 1, []); - const fee = this.safeFloat (fees, 1); + const fee = this.safeNumber (fees, 1); + const undl = this.safeValue (indexed['undl'], id, []); const precision = 8; // default precision, todo: fix "magic constants" - id = 'f' + id; + const fid = 'f' + id; result[code] = { - 'id': id, + 'id': fid, 'code': code, - 'info': [ id, label, pool, feeValues ], + 'info': [ id, label, pool, feeValues, undl ], 'type': type, 'name': name, 'active': true, @@ -16176,40 +17972,117 @@ module.exports = class bitfinex2 extends bitfinex { async fetchBalance (params = {}) { // this api call does not return the 'used' amount - use the v1 version instead (which also returns zero balances) + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 await this.loadMarkets (); - const response = await this.privatePostAuthRWallets (params); - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } + const isDerivative = requestedType === 'derivatives'; + const query = this.omit (params, 'type'); + const response = await this.privatePostAuthRWallets (query); const result = { 'info': response }; - for (let b = 0; b < response.length; b++) { - const balance = response[b]; - const accountType = balance[0]; - let currency = balance[1]; - const total = balance[2]; - const available = balance[4]; - if (accountType === balanceType) { - if (currency[0] === 't') { - currency = currency.slice (1); - } - const code = this.safeCurrencyCode (currency); + for (let i = 0; i < response.length; i++) { + const balance = response[i]; + const type = this.safeString (balance, 0); + const currencyId = this.safeStringLower (balance, 1, ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { + const code = this.safeCurrencyCode (currencyId); const account = this.account (); - // do not fill in zeroes and missing values in the parser - // rewrite and unify the following to use the unified parseBalance - account['total'] = total; - if (!available) { - if (available === 0) { - account['free'] = 0; - account['used'] = total; - } else { - account['free'] = total; - } - } else { - account['free'] = available; - account['used'] = account['total'] - account['free']; - } + account['total'] = this.safeString (balance, 2); + account['free'] = this.safeString (balance, 4); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currency = this.currency (code); + const fromCurrencyId = this.convertDerivativesId (currency, fromAccount); + const toCurrencyId = this.convertDerivativesId (currency, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + // this request is slightly different from v1 fromAccount -> from + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'from': fromId, + 'to': toId, + }; + const response = await this.privatePostAuthWTransfer (this.extend (request, params)); + // [1616451183763,"acc_tf",null,null,[1616451183763,"exchange","margin",null,"UST","UST",null,1],null,"SUCCESS","1.0 Tether USDt transfered from Exchange to Margin"] + const timestamp = this.safeInteger (response, 0); + // ["error",10001,"Momentary balance check. Please wait few seconds and try the transfer again."] + const error = this.safeString (response, 0); + if (error === 'error') { + const message = this.safeString (response, 2, ''); + // same message as in v1 + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + const info = this.safeValue (response, 4); + const fromResponse = this.safeString (info, 1); + const toResponse = this.safeString (info, 2); + const toCode = this.safeCurrencyCode (this.safeString (info, 5)); + const success = this.safeString (response, 6); + const status = (success === 'SUCCESS') ? 'ok' : undefined; + return { + 'info': response, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'status': status, + 'amount': requestedAmount, + 'code': toCode, + 'fromAccount': fromResponse, + 'toAccount': toResponse, + }; + } + + convertDerivativesId (currency, type) { + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 + // { + // id: 'fUSTF0', + // code: 'USTF0', + // info: [ 'USTF0', [], [], [], [ 'USTF0', 'UST' ] ], + const info = this.safeValue (currency, 'info'); + const transferId = this.safeString (info, 0); + const underlying = this.safeValue (info, 4, []); + let currencyId = undefined; + if (type === 'derivatives') { + currencyId = this.safeString (underlying, 0, transferId); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if (!isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + } else if (type !== 'margin') { + currencyId = this.safeString (underlying, 1, transferId); + } else { + currencyId = transferId; + } + return currencyId; } async fetchOrder (id, symbol = undefined, params = {}) { @@ -16239,9 +18112,10 @@ module.exports = class bitfinex2 extends bitfinex { const priceIndex = (fullRequest['precision'] === 'R0') ? 1 : 0; for (let i = 0; i < orderbook.length; i++) { const order = orderbook[i]; - const price = order[priceIndex]; - const amount = Math.abs (order[2]); - const side = (order[2] > 0) ? 'bids' : 'asks'; + const price = this.safeNumber (order, priceIndex); + const signedAmount = this.safeNumber (order, 2); + const amount = Math.abs (signedAmount); + const side = (signedAmount > 0) ? 'bids' : 'asks'; result[side].push ([ price, amount ]); } result['bids'] = this.sortBy (result['bids'], 0, true); @@ -16256,26 +18130,26 @@ module.exports = class bitfinex2 extends bitfinex { symbol = market['symbol']; } const length = ticker.length; - const last = ticker[length - 4]; + const last = this.safeNumber (ticker, length - 4); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': ticker[length - 2], - 'low': ticker[length - 1], - 'bid': ticker[length - 10], + 'high': this.safeNumber (ticker, length - 2), + 'low': this.safeNumber (ticker, length - 1), + 'bid': this.safeNumber (ticker, length - 10), 'bidVolume': undefined, - 'ask': ticker[length - 8], + 'ask': this.safeNumber (ticker, length - 8), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': ticker[length - 6], - 'percentage': ticker[length - 5] * 100, + 'change': this.safeNumber (ticker, length - 6), + 'percentage': this.safeNumber (ticker, length - 5) * 100, 'average': undefined, - 'baseVolume': ticker[length - 3], + 'baseVolume': this.safeNumber (ticker, length - 3), 'quoteVolume': undefined, 'info': ticker, }; @@ -16364,12 +18238,12 @@ module.exports = class bitfinex2 extends bitfinex { // const tradeLength = trade.length; const isPrivate = (tradeLength > 5); - const id = trade[0].toString (); + const id = this.safeString (trade, 0); const amountIndex = isPrivate ? 4 : 2; - let amount = trade[amountIndex]; + let amount = this.safeNumber (trade, amountIndex); let cost = undefined; const priceIndex = isPrivate ? 5 : 3; - const price = trade[priceIndex]; + const price = this.safeNumber (trade, priceIndex); let side = undefined; let orderId = undefined; let takerOrMaker = undefined; @@ -16377,7 +18251,7 @@ module.exports = class bitfinex2 extends bitfinex { let fee = undefined; let symbol = undefined; const timestampIndex = isPrivate ? 2 : 1; - const timestamp = trade[timestampIndex]; + const timestamp = this.safeInteger (trade, timestampIndex); if (isPrivate) { const marketId = trade[1]; if (marketId in this.markets_by_id) { @@ -16386,10 +18260,12 @@ module.exports = class bitfinex2 extends bitfinex { } else { symbol = this.parseSymbol (marketId); } - orderId = trade[3].toString (); - takerOrMaker = (trade[8] === 1) ? 'maker' : 'taker'; - let feeCost = trade[9]; - const feeCurrency = this.safeCurrencyCode (trade[10]); + orderId = this.safeString (trade, 3); + const maker = this.safeInteger (trade, 8); + takerOrMaker = (maker === 1) ? 'maker' : 'taker'; + let feeCost = this.safeNumber (trade, 9); + const feeCurrencyId = this.safeString (trade, 10); + const feeCurrency = this.safeCurrencyCode (feeCurrencyId); if (feeCost !== undefined) { feeCost = -feeCost; if (symbol in this.markets) { @@ -16530,10 +18406,10 @@ module.exports = class bitfinex2 extends bitfinex { // https://github.com/ccxt/ccxt/issues/6686 // const timestamp = this.safeTimestamp (order, 5); const timestamp = this.safeInteger (order, 5); - const remaining = Math.abs (this.safeFloat (order, 6)); - const amount = Math.abs (this.safeFloat (order, 7)); - const filled = amount - remaining; - const side = (order[7] < 0) ? 'sell' : 'buy'; + const remaining = Math.abs (this.safeNumber (order, 6)); + const signedAmount = this.safeNumber (order, 7); + const amount = Math.abs (signedAmount); + const side = (signedAmount < 0) ? 'sell' : 'buy'; const orderType = this.safeString (order, 8); const type = this.safeString (this.safeValue (this.options, 'exchangeTypes'), orderType); let status = undefined; @@ -16542,11 +18418,10 @@ module.exports = class bitfinex2 extends bitfinex { const parts = statusString.split (' @ '); status = this.parseOrderStatus (this.safeString (parts, 0)); } - const price = this.safeFloat (order, 16); - const average = this.safeFloat (order, 17); - const cost = price * filled; + const price = this.safeNumber (order, 16); + const average = this.safeNumber (order, 17); const clientOrderId = this.safeString (order, 2); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -16561,14 +18436,14 @@ module.exports = class bitfinex2 extends bitfinex { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -16585,11 +18460,11 @@ module.exports = class bitfinex2 extends bitfinex { if ((orderType === 'LIMIT') || (orderType === 'EXCHANGE LIMIT')) { request['price'] = this.numberToString (price); } else if ((orderType === 'STOP') || (orderType === 'EXCHANGE STOP')) { - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'STOP LIMIT') || (orderType === 'EXCHANGE STOP LIMIT')) { - const priceAuxLimit = this.safeFloat (params, 'price_aux_limit'); - let stopPrice = this.safeFloat (params, 'stopPrice'); + const priceAuxLimit = this.safeNumber (params, 'price_aux_limit'); + let stopPrice = this.safeNumber (params, 'stopPrice'); if (priceAuxLimit === undefined) { if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter or a price_aux_limit parameter for a ' + orderType + ' order'); @@ -16604,9 +18479,9 @@ module.exports = class bitfinex2 extends bitfinex { } request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'TRAILING STOP') || (orderType === 'EXCHANGE TRAILING STOP')) { - const priceTrailing = this.safeFloat (params, 'price_trailing'); + const priceTrailing = this.safeNumber (params, 'price_trailing'); request['price_trailing'] = this.numberToString (priceTrailing); - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'FOK') || (orderType === 'EXCHANGE FOK') || (orderType === 'IOC') || (orderType === 'EXCHANGE IOC')) { request['price'] = this.numberToString (price); @@ -16938,11 +18813,11 @@ module.exports = class bitfinex2 extends bitfinex { if (currency !== undefined) { code = currency['code']; } - feeCost = this.safeFloat (data, 8); + feeCost = this.safeNumber (data, 8); if (feeCost !== undefined) { feeCost = -feeCost; } - amount = this.safeFloat (data, 5); + amount = this.safeNumber (data, 5); id = this.safeValue (data, 0); status = 'ok'; if (id === 0) { @@ -16956,7 +18831,7 @@ module.exports = class bitfinex2 extends bitfinex { timestamp = this.safeInteger (transaction, 5); updated = this.safeInteger (transaction, 6); status = this.parseTransactionStatus (this.safeString (transaction, 9)); - amount = this.safeFloat (transaction, 12); + amount = this.safeNumber (transaction, 12); if (amount !== undefined) { if (amount < 0) { type = 'withdrawal'; @@ -16964,7 +18839,7 @@ module.exports = class bitfinex2 extends bitfinex { type = 'deposit'; } } - feeCost = this.safeFloat (transaction, 13); + feeCost = this.safeNumber (transaction, 13); if (feeCost !== undefined) { feeCost = -feeCost; } @@ -17092,7 +18967,7 @@ module.exports = class bitfinex2 extends bitfinex { }); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // @@ -17197,13 +19072,14 @@ module.exports = class bitfinex2 extends bitfinex { } }; -},{"./base/errors":8,"./bitfinex.js":29}],31:[function(require,module,exports){ +},{"./base/errors":9,"./bitfinex.js":30}],32:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -17385,11 +19261,11 @@ module.exports = class bitflyer extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'amount'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -17408,16 +19284,16 @@ module.exports = class bitflyer extends Exchange { }; const ticker = await this.publicGetGetticker (this.extend (request, params)); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'ltp'); + const last = this.safeNumber (ticker, 'ltp'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'best_bid'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -17427,7 +19303,7 @@ module.exports = class bitflyer extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_by_product'), + 'baseVolume': this.safeNumber (ticker, 'volume_by_product'), 'quoteVolume': undefined, 'info': ticker, }; @@ -17451,14 +19327,11 @@ module.exports = class bitflyer extends Exchange { order = this.safeString (trade, 'child_order_acceptance_id'); } const timestamp = this.parse8601 (this.safeString (trade, 'exec_date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -17534,18 +19407,17 @@ module.exports = class bitflyer extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'child_order_date')); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'outstanding_size'); - const filled = this.safeFloat (order, 'executed_size'); - const price = this.safeFloat (order, 'price'); - const cost = price * filled; + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'outstanding_size'); + const filled = this.safeNumber (order, 'executed_size'); + const price = this.safeNumber (order, 'price'); const status = this.parseOrderStatus (this.safeString (order, 'child_order_state')); const type = this.safeStringLower (order, 'child_order_type'); const side = this.safeStringLower (order, 'side'); const marketId = this.safeString (order, 'product_code'); const symbol = this.safeSymbol (marketId, market); let fee = undefined; - const feeCost = this.safeFloat (order, 'total_commission'); + const feeCost = this.safeNumber (order, 'total_commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -17554,7 +19426,7 @@ module.exports = class bitflyer extends Exchange { }; } const id = this.safeString (order, 'child_order_acceptance_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -17569,14 +19441,14 @@ module.exports = class bitflyer extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) { @@ -17639,7 +19511,7 @@ module.exports = class bitflyer extends Exchange { return this.parseTrades (response, market, since, limit); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { if (symbols === undefined) { throw new ArgumentsRequired (this.id + ' fetchPositions() requires a `symbols` argument, exactly one symbol in an array'); } @@ -17723,13 +19595,14 @@ module.exports = class bitflyer extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],32:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],33:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, OrderNotFound, InsufficientFunds, DDoSProtection, PermissionDenied, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -17985,7 +19858,7 @@ module.exports = class bitforex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -18021,14 +19894,11 @@ module.exports = class bitforex extends Exchange { const timestamp = this.safeInteger (trade, 'time'); const id = this.safeString (trade, 'tid'); const orderId = undefined; - const amount = this.safeFloat (trade, 'amount'); - const price = this.safeFloat (trade, 'price'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const sideId = this.safeInteger (trade, 'direction'); const side = this.parseSide (sideId); return { @@ -18071,12 +19941,12 @@ module.exports = class bitforex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'active'); - account['total'] = this.safeFloat (balance, 'fix'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'active'); + account['total'] = this.safeString (balance, 'fix'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTicker (symbol, params = {}) { @@ -18092,21 +19962,21 @@ module.exports = class bitforex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (data, 'high'), - 'low': this.safeFloat (data, 'low'), - 'bid': this.safeFloat (data, 'buy'), + 'high': this.safeNumber (data, 'high'), + 'low': this.safeNumber (data, 'low'), + 'bid': this.safeNumber (data, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (data, 'sell'), + 'ask': this.safeNumber (data, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (data, 'last'), - 'last': this.safeFloat (data, 'last'), + 'close': this.safeNumber (data, 'last'), + 'last': this.safeNumber (data, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (data, 'vol'), + 'baseVolume': this.safeNumber (data, 'vol'), 'quoteVolume': undefined, 'info': response, }; @@ -18126,11 +19996,11 @@ module.exports = class bitforex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -18198,26 +20068,24 @@ module.exports = class bitforex extends Exchange { parseOrder (order, market = undefined) { const id = this.safeString (order, 'orderId'); - const timestamp = this.safeFloat (order, 'createTime'); - const lastTradeTimestamp = this.safeFloat (order, 'lastTime'); + const timestamp = this.safeNumber (order, 'createTime'); + const lastTradeTimestamp = this.safeNumber (order, 'lastTime'); const symbol = market['symbol']; const sideId = this.safeInteger (order, 'tradeType'); const side = this.parseSide (sideId); const type = undefined; - const price = this.safeFloat (order, 'orderPrice'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderAmount'); - const filled = this.safeFloat (order, 'dealAmount'); - const remaining = amount - filled; + const price = this.safeNumber (order, 'orderPrice'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderAmount'); + const filled = this.safeNumber (order, 'dealAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderState')); - const cost = filled * price; const feeSide = (side === 'buy') ? 'base' : 'quote'; const feeCurrency = market[feeSide]; const fee = { - 'cost': this.safeFloat (order, 'tradeFee'), + 'cost': this.safeNumber (order, 'tradeFee'), 'currency': feeCurrency, }; - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -18231,16 +20099,15 @@ module.exports = class bitforex extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -18356,7 +20223,7 @@ module.exports = class bitforex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],33:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],34:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -18364,6 +20231,7 @@ module.exports = class bitforex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -19152,7 +21020,7 @@ module.exports = class bitget extends Exchange { let swap = false; const baseId = this.safeString2 (market, 'base_currency', 'coin'); const quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { marketType = 'swap'; spot = false; @@ -19170,7 +21038,7 @@ module.exports = class bitget extends Exchange { 'amount': parseFloat ('1e-' + sizeIncrement), 'price': parseFloat ('1e-' + tickSize), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const status = this.safeString (market, 'status'); let active = undefined; if (status !== undefined) { @@ -19427,26 +21295,26 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat2 (ticker, 'last', 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'last', 'close'); + const open = this.safeNumber (ticker, 'open'); let bidVolume = undefined; let askVolume = undefined; let bid = this.safeValue (ticker, 'bid'); if (bid === undefined) { - bid = this.safeFloat (ticker, 'best_bid'); + bid = this.safeNumber (ticker, 'best_bid'); } else { - bidVolume = this.safeFloat (bid, 1); - bid = this.safeFloat (bid, 0); + bidVolume = this.safeNumber (bid, 1); + bid = this.safeNumber (bid, 0); } let ask = this.safeValue (ticker, 'ask'); if (ask === undefined) { - ask = this.safeFloat (ticker, 'best_ask'); + ask = this.safeNumber (ticker, 'best_ask'); } else { - askVolume = this.safeFloat (ask, 1); - ask = this.safeFloat (ask, 0); + askVolume = this.safeNumber (ask, 1); + ask = this.safeNumber (ask, 0); } - const baseVolume = this.safeFloat2 (ticker, 'amount', 'volume_24h'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber2 (ticker, 'amount', 'volume_24h'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; @@ -19460,8 +21328,8 @@ module.exports = class bitget extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -19696,9 +21564,12 @@ module.exports = class bitget extends Exchange { } let timestamp = this.safeInteger (trade, 'created_at'); timestamp = this.safeInteger2 (trade, 'timestamp', 'ts', timestamp); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'filled_amount', 'order_qty'); - amount = this.safeFloat2 (trade, 'size', 'amount', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'filled_amount', 'order_qty'); + amountString = this.safeString2 (trade, 'size', 'amount', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -19717,18 +21588,13 @@ module.exports = class bitget extends Exchange { type = this.parseOrderType (side); side = this.parseOrderSide (side); } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - let feeCost = this.safeFloat (trade, 'fee'); - if (feeCost === undefined) { - feeCost = this.safeFloat (trade, 'filled_fees'); + let feeCostString = this.safeString (trade, 'fee'); + if (feeCostString === undefined) { + feeCostString = this.safeString (trade, 'filled_fees'); } else { - feeCost = -feeCost; + feeCostString = (feeCostString[0] === '-') ? feeCostString.slice (1) : feeCostString; } + const feeCost = this.parseNumber (feeCostString); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -19851,23 +21717,23 @@ module.exports = class bitget extends Exchange { const volumeIndex = this.safeString (volume, market['type'], 'amount'); return [ this.safeInteger (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets ]; } else { const volumeIndex = this.safeValue (volume, market['type'], 6); return [ this.safeInteger (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, volumeIndex), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, volumeIndex), // Base Volume ]; } } @@ -19969,13 +21835,13 @@ module.exports = class bitget extends Exchange { } const type = this.safeValue (balance, 'type'); if (type === 'trade') { - result[code]['free'] = this.safeFloat (balance, 'balance'); + result[code]['free'] = this.safeString (balance, 'balance'); } else if ((type === 'frozen') || (type === 'lock')) { - const used = this.safeFloat (result[code], 'used'); - result[code]['used'] = this.sum (used, this.safeFloat (balance, 'balance')); + const used = this.safeString (result[code], 'used'); + result[code]['used'] = Precise.stringAdd (used, this.safeString (balance, 'balance')); } } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseSwapBalance (response) { @@ -19999,11 +21865,11 @@ module.exports = class bitget extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeString (balance, 'equity'); + account['free'] = this.safeString (balance, 'total_avail_balance'); result[symbol] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchAccounts (params = {}) { @@ -20280,26 +22146,13 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let amount = this.safeFloat2 (order, 'amount', 'size'); - const filled = this.safeFloat2 (order, 'filled_amount', 'filled_qty'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - amount = Math.max (amount, filled); - remaining = Math.max (0, amount - filled); - } - } - if (type === 'market') { - remaining = 0; - } - const cost = this.safeFloat (order, 'filled_cash_amount'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); - if ((average === undefined) && (filled !== undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } + const amount = this.safeNumber2 (order, 'amount', 'size'); + const filled = this.safeNumber2 (order, 'filled_amount', 'filled_qty'); + const cost = this.safeNumber (order, 'filled_cash_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'price_avg'); const status = this.parseOrderStatus (this.safeString2 (order, 'state', 'status')); - const feeCost = this.safeFloat2 (order, 'filled_fees', 'fee'); + const feeCost = this.safeNumber2 (order, 'filled_fees', 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -20309,7 +22162,7 @@ module.exports = class bitget extends Exchange { }; } const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -20327,11 +22180,11 @@ module.exports = class bitget extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -20378,7 +22231,7 @@ module.exports = class bitget extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'amount'); + let cost = this.safeNumber (params, 'amount'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -20928,12 +22781,12 @@ module.exports = class bitget extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const txid = this.safeString (transaction, 'tx_hash'); const timestamp = this.safeInteger (transaction, 'created_at'); const updated = this.safeInteger (transaction, 'updated_at'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -21123,7 +22976,7 @@ module.exports = class bitget extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.swapGetPositionAllPosition (params); // @@ -21264,7 +23117,7 @@ module.exports = class bitget extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],34:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],35:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -21272,6 +23125,7 @@ module.exports = class bitget extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); const { DECIMAL_PLACES, SIGNIFICANT_DIGITS, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -21465,12 +23319,12 @@ module.exports = class bithumb extends Exchange { const account = this.account (); const currency = this.currency (code); const lowerCurrencyId = this.safeStringLower (currency, 'id'); - account['total'] = this.safeFloat (balances, 'total_' + lowerCurrencyId); - account['used'] = this.safeFloat (balances, 'in_use_' + lowerCurrencyId); - account['free'] = this.safeFloat (balances, 'available_' + lowerCurrencyId); + account['total'] = this.safeString (balances, 'total_' + lowerCurrencyId); + account['used'] = this.safeString (balances, 'in_use_' + lowerCurrencyId); + account['free'] = this.safeString (balances, 'available_' + lowerCurrencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -21532,8 +23386,8 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'opening_price'); - const close = this.safeFloat (ticker, 'closing_price'); + const open = this.safeNumber (ticker, 'opening_price'); + const close = this.safeNumber (ticker, 'closing_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -21544,18 +23398,18 @@ module.exports = class bithumb extends Exchange { } average = this.sum (open, close) / 2; } - const baseVolume = this.safeFloat (ticker, 'units_traded_24H'); - const quoteVolume = this.safeFloat (ticker, 'acc_trade_value_24H'); + const baseVolume = this.safeNumber (ticker, 'units_traded_24H'); + const quoteVolume = this.safeNumber (ticker, 'acc_trade_value_24H'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -21661,11 +23515,11 @@ module.exports = class bithumb extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -21755,18 +23609,16 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'units_traded', 'units'); - let cost = this.safeFloat (trade, 'total'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'units_traded', 'units'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId); @@ -21969,14 +23821,14 @@ module.exports = class bithumb extends Exchange { const sideProperty = this.safeValue2 (order, 'type', 'side'); const side = (sideProperty === 'bid') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'order_status')); - let price = this.safeFloat2 (order, 'order_price', 'price'); + let price = this.safeNumber2 (order, 'order_price', 'price'); let type = 'limit'; if (price === 0) { price = undefined; type = 'market'; } - const amount = this.safeFloat2 (order, 'order_qty', 'units'); - let remaining = this.safeFloat (order, 'units_remaining'); + const amount = this.safeNumber2 (order, 'order_qty', 'units'); + let remaining = this.safeNumber (order, 'units_remaining'); if (remaining === undefined) { if (status === 'closed') { remaining = 0; @@ -21995,65 +23847,14 @@ module.exports = class bithumb extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let filled = undefined; - let cost = undefined; - let average = undefined; const id = this.safeString (order, 'order_id'); - const rawTrades = this.safeValue (order, 'contract'); - let trades = undefined; - let fee = undefined; - let fees = undefined; - let feesByCurrency = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'side': side, - 'symbol': symbol, - 'order': id, - }); - filled = 0; - feesByCurrency = {}; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - filled = this.sum (filled, trade['amount']); - cost = this.sum (cost, trade['cost']); - const tradeFee = trade['fee']; - const feeCurrency = tradeFee['currency']; - if (feeCurrency in feesByCurrency) { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': this.sum (feesByCurrency[feeCurrency]['cost'], tradeFee['cost']), - }; - } else { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': tradeFee['cost'], - }; - } - } - const feeCurrencies = Object.keys (feesByCurrency); - const feeCurrenciesLength = feeCurrencies.length; - if (feeCurrenciesLength > 1) { - fees = []; - for (let i = 0; i < feeCurrencies.length; i++) { - const feeCurrency = feeCurrencies[i]; - fees.push (feesByCurrency[feeCurrency]); - } - } else { - fee = this.safeValue (feesByCurrency, feeCurrencies[0]); - } - if (filled !== 0) { - average = cost / filled; - } - } - if (amount !== undefined) { - if ((filled === undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if ((remaining === undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const result = { + const rawTrades = this.safeValue (order, 'contract', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'side': side, + 'symbol': symbol, + 'order': id, + }); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -22068,20 +23869,14 @@ module.exports = class bithumb extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, + 'cost': undefined, + 'average': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': trades, - }; - if (fee !== undefined) { - result['fee'] = fee; - } else if (fees !== undefined) { - result['fees'] = fees; - } - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -22241,7 +24036,7 @@ module.exports = class bithumb extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],35:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],36:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -22272,7 +24067,7 @@ module.exports = class bitkk extends zb { } }; -},{"./zb.js":182}],36:[function(require,module,exports){ +},{"./zb.js":178}],37:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -22710,16 +24505,16 @@ module.exports = class bitmart extends Exchange { // const pricePrecision = this.safeInteger (market, 'price_max_precision'); const precision = { - 'amount': this.safeFloat (market, 'base_min_size'), + 'amount': this.safeNumber (market, 'base_min_size'), 'price': parseFloat (this.decimalToPrecision (Math.pow (10, -pricePrecision), ROUND, 10)), }; - const minBuyCost = this.safeFloat (market, 'min_buy_amount'); - const minSellCost = this.safeFloat (market, 'min_sell_amount'); + const minBuyCost = this.safeNumber (market, 'min_buy_amount'); + const minSellCost = this.safeNumber (market, 'min_sell_amount'); const minCost = Math.max (minBuyCost, minSellCost); const limits = { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': { 'min': undefined, @@ -22829,16 +24624,16 @@ module.exports = class bitmart extends Exchange { // // the docs are wrong: https://github.com/ccxt/ccxt/issues/5612 // - const amountPrecision = this.safeFloat (contract, 'vol_unit'); - const pricePrecision = this.safeFloat (contract, 'price_unit'); + const amountPrecision = this.safeNumber (contract, 'vol_unit'); + const pricePrecision = this.safeNumber (contract, 'price_unit'); const precision = { 'amount': amountPrecision, 'price': pricePrecision, }; const limits = { 'amount': { - 'min': this.safeFloat (contract, 'min_vol'), - 'max': this.safeFloat (contract, 'max_vol'), + 'min': this.safeNumber (contract, 'min_vol'), + 'max': this.safeNumber (contract, 'max_vol'), }, 'price': { 'min': undefined, @@ -22861,8 +24656,8 @@ module.exports = class bitmart extends Exchange { future = true; } const feeConfig = this.safeValue (market, 'fee_config', {}); - const maker = this.safeFloat (feeConfig, 'maker_fee'); - const taker = this.safeFloat (feeConfig, 'taker_fee'); + const maker = this.safeNumber (feeConfig, 'maker_fee'); + const taker = this.safeNumber (feeConfig, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -22950,33 +24745,33 @@ module.exports = class bitmart extends Exchange { const timestamp = this.safeTimestamp (ticker, 'timestamp', this.milliseconds ()); const marketId = this.safeString2 (ticker, 'symbol', 'contract_id'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat2 (ticker, 'close_24h', 'last_price'); - let percentage = this.safeFloat (ticker, 'fluctuation', 'rise_fall_rate'); + const last = this.safeNumber2 (ticker, 'close_24h', 'last_price'); + let percentage = this.safeNumber (ticker, 'fluctuation', 'rise_fall_rate'); if (percentage !== undefined) { percentage *= 100; } - const baseVolume = this.safeFloat2 (ticker, 'base_volume_24h', 'base_coin_volume'); - const quoteVolume = this.safeFloat2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); + const baseVolume = this.safeNumber2 (ticker, 'base_volume_24h', 'base_coin_volume'); + const quoteVolume = this.safeNumber2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const open = this.safeFloat2 (ticker, 'open_24h', 'open'); + const open = this.safeNumber2 (ticker, 'open_24h', 'open'); let average = undefined; if ((last !== undefined) && (open !== undefined)) { average = this.sum (last, open) / 2; } - average = this.safeFloat (ticker, 'avg_price', average); + average = this.safeNumber (ticker, 'avg_price', average); const price = this.safeValue (ticker, 'depth_price', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), - 'bid': this.safeFloat (price, 'best_bid', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (price, 'best_ask', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), + 'bid': this.safeNumber (price, 'best_bid', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (price, 'best_ask', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open_24h'), + 'open': this.safeNumber (ticker, 'open_24h'), 'close': last, 'last': last, 'previousClose': undefined, @@ -23280,18 +25075,18 @@ module.exports = class bitmart extends Exchange { if (execType !== undefined) { takerOrMaker = (execType === 'M') ? 'maker' : 'taker'; } - let price = this.safeFloat2 (trade, 'price', 'deal_price'); - price = this.safeFloat (trade, 'price_avg', price); - let amount = this.safeFloat2 (trade, 'amount', 'deal_vol'); - amount = this.safeFloat (trade, 'size', amount); - let cost = this.safeFloat2 (trade, 'count', 'notional'); + let price = this.safeNumber2 (trade, 'price', 'deal_price'); + price = this.safeNumber (trade, 'price_avg', price); + let amount = this.safeNumber2 (trade, 'amount', 'deal_vol'); + amount = this.safeNumber (trade, 'size', amount); + let cost = this.safeNumber2 (trade, 'count', 'notional'); if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { cost = amount * price; } const orderId = this.safeInteger (trade, 'order_id'); const marketId = this.safeString2 (trade, 'contract_id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (trade, 'fees'); + const feeCost = this.safeNumber (trade, 'fees'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_coin_name'); @@ -23419,11 +25214,11 @@ module.exports = class bitmart extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -23750,11 +25545,11 @@ module.exports = class bitmart extends Exchange { currencyId = this.safeString (balance, 'coind_code', currencyId); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat2 (balance, 'available', 'available_vol'); - account['used'] = this.safeFloat2 (balance, 'frozen', 'freeze_vol'); + account['free'] = this.safeString2 (balance, 'available', 'available_vol'); + account['used'] = this.safeString2 (balance, 'frozen', 'freeze_vol'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -23823,29 +25618,10 @@ module.exports = class bitmart extends Exchange { if (market !== undefined) { status = this.parseOrderStatusByType (market['type'], this.safeString (order, 'status')); } - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat2 (order, 'price_avg', 'done_avg_price'); - const amount = this.safeFloat2 (order, 'size', 'vol'); - let cost = undefined; - let filled = this.safeFloat2 (order, 'filled_size', 'done_vol'); - let remaining = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - if (filled === undefined) { - filled = Math.max (0, amount - remaining); - } - } - if (filled !== undefined) { - if (remaining === undefined) { - remaining = Math.max (0, amount - filled); - } - if (cost === undefined) { - if (average !== undefined) { - cost = average * filled; - } - } - } - } + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber2 (order, 'price_avg', 'done_avg_price'); + const amount = this.safeNumber2 (order, 'size', 'vol'); + const filled = this.safeNumber2 (order, 'filled_size', 'done_vol'); let side = this.safeString (order, 'side'); // 1 = Open long // 2 = Close short @@ -23867,7 +25643,7 @@ module.exports = class bitmart extends Exchange { average = undefined; } } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -23882,14 +25658,14 @@ module.exports = class bitmart extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatusByType (type, status) { @@ -23930,7 +25706,7 @@ module.exports = class bitmart extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -24516,12 +26292,12 @@ module.exports = class bitmart extends Exchange { type = 'deposit'; id = depositId; } - const amount = this.safeFloat (transaction, 'arrival_amount'); + const amount = this.safeNumber (transaction, 'arrival_amount'); const timestamp = this.safeInteger (transaction, 'tapply_timeime'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -24637,1735 +26413,7 @@ module.exports = class bitmart extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],37:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); - -// --------------------------------------------------------------------------- - -module.exports = class bitmax extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'bitmax', - 'name': 'BitMax', - 'countries': [ 'CN' ], // China - 'rateLimit': 500, - // new metainfo interface - 'has': { - 'CORS': false, - 'fetchMarkets': true, - 'fetchCurrencies': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchOHLCV': true, - 'fetchTrades': true, - 'fetchAccounts': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'cancelAllOrders': true, - 'fetchDepositAddress': true, - 'fetchTransactions': true, - 'fetchDeposits': true, - 'fetchWithdrawals': true, - 'fetchOrder': true, - 'fetchOrders': true, - 'fetchOpenOrders': true, - 'fetchClosedOrders': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '6h': '360', - '12h': '720', - '1d': '1d', - '1w': '1w', - '1M': '1m', - }, - 'version': 'v1', - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg', - 'api': 'https://bitmax.io', - 'test': 'https://bitmax-test.io', - 'www': 'https://bitmax.io', - 'doc': [ - 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', - ], - 'fees': 'https://bitmax.io/#/feeRate/tradeRate', - 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', - }, - 'api': { - 'public': { - 'get': [ - 'assets', - 'products', - 'ticker', - 'barhist/info', - 'barhist', - 'depth', - 'trades', - 'cash/assets', // not documented - 'cash/products', // not documented - 'margin/assets', // not documented - 'margin/products', // not documented - 'futures/collateral', - 'futures/contracts', - 'futures/ref-px', - 'futures/market-data', - 'futures/funding-rates', - ], - }, - 'accountCategory': { - 'get': [ - 'balance', - 'order/open', - 'order/status', - 'order/hist/current', - 'risk', - ], - 'post': [ - 'order', - 'order/batch', - ], - 'delete': [ - 'order', - 'order/all', - 'order/batch', - ], - }, - 'accountGroup': { - 'get': [ - 'cash/balance', - 'margin/balance', - 'margin/risk', - 'transfer', - 'futures/collateral-balance', - 'futures/position', - 'futures/risk', - 'futures/funding-payments', - 'order/hist', - ], - 'post': [ - 'futures/transfer/deposit', - 'futures/transfer/withdraw', - ], - }, - 'private': { - 'get': [ - 'info', - 'wallet/transactions', - 'wallet/deposit/address', // not documented - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'taker': 0.002, - 'maker': 0.002, - }, - }, - 'precisionMode': TICK_SIZE, - 'options': { - 'account-category': 'cash', // 'cash'/'margin'/'futures' - 'account-group': undefined, - 'fetchClosedOrders': { - 'method': 'accountGroupGetOrderHist', // 'accountGroupGetAccountCategoryOrderHistCurrent' - }, - }, - 'exceptions': { - 'exact': { - // not documented - '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"} - '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"} - '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"} - '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."} - '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'} - '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' } - '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."} - // documented - '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid - '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing - '100003': BadRequest, // KEY_CONFLICT The same key exists already - '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument - '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument - '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid - '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption - '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request - '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request - '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account - '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp - '100012': BadRequest, // INVALID_STR_FORMAT String format does not - '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input - '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error - '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object - '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed - '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times - '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist - '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly - '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist - '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error - '200007': ExchangeError, // CODE_NOT_FOUND - '200008': ExchangeError, // CODE_EXPIRED Code expired - '200009': ExchangeError, // CODE_MISMATCH Code does not match - '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword - '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly - '200012': ExchangeError, // FAKE_COKE_VERIFY - '200013': ExchangeError, // SECURITY_ALERT Provide security alert message - '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw. - '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation - '300001': InvalidOrder, // INVALID_PRICE Order price is invalid - '300002': InvalidOrder, // INVALID_QTY Order size is invalid - '300003': InvalidOrder, // INVALID_SIDE Order side is invalid - '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large - '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid - '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid - '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid - '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid - '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset - '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading - '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange - '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request - '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset - '300021': InvalidOrder, // TRADING_DISABLED Trading is disabled on account or asset - '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading - '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance - '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading - '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high - '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading - '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price - '510001': ExchangeError, // SERVER_ERROR Something wrong with server. - '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass - }, - 'broad': {}, - }, - 'commonCurrencies': { - 'BTCBEAR': 'BEAR', - 'BTCBULL': 'BULL', - }, - }); - } - - getAccount (params = {}) { - // get current or provided bitmax sub-account - const account = this.safeValue (params, 'account', this.options['account']); - return account.toLowerCase ().capitalize (); - } - - async fetchCurrencies (params = {}) { - const assets = await this.publicGetAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode" : "LTCBULL", - // "assetName" : "3X Long LTC Token", - // "precisionScale" : 9, - // "nativeScale" : 4, - // "withdrawalFee" : "0.2", - // "minWithdrawalAmt" : "1.0", - // "status" : "Normal" - // }, - // ] - // } - // - const margin = await this.publicGetMarginAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode":"BTT", - // "borrowAssetCode":"BTT-B", - // "interestAssetCode":"BTT-I", - // "nativeScale":0, - // "numConfirmations":1, - // "withdrawFee":"100.0", - // "minWithdrawalAmt":"1000.0", - // "statusCode":"Normal", - // "statusMessage":"", - // "interestRate":"0.001" - // } - // ] - // } - // - const cash = await this.publicGetCashAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode":"LTCBULL", - // "nativeScale":4, - // "numConfirmations":20, - // "withdrawFee":"0.2", - // "minWithdrawalAmt":"1.0", - // "statusCode":"Normal", - // "statusMessage":"" - // } - // ] - // } - // - const assetsData = this.safeValue (assets, 'data', []); - const marginData = this.safeValue (margin, 'data', []); - const cashData = this.safeValue (cash, 'data', []); - const assetsById = this.indexBy (assetsData, 'assetCode'); - const marginById = this.indexBy (marginData, 'assetCode'); - const cashById = this.indexBy (cashData, 'assetCode'); - const dataById = this.deepExtend (assetsById, marginById, cashById); - const ids = Object.keys (dataById); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const currency = dataById[id]; - const code = this.safeCurrencyCode (id); - const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); - // why would the exchange API have different names for the same field - const fee = this.safeFloat2 (currency, 'withdrawFee', 'withdrawalFee'); - const status = this.safeString2 (currency, 'status', 'statusCode'); - const active = (status === 'Normal'); - const margin = ('borrowAssetCode' in currency); - result[code] = { - 'id': id, - 'code': code, - 'info': currency, - 'type': undefined, - 'margin': margin, - 'name': this.safeString (currency, 'assetName'), - 'active': active, - 'fee': fee, - 'precision': precision, - 'limits': { - 'amount': { - 'min': Math.pow (10, -precision), - 'max': undefined, - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': undefined, - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawalAmt'), - 'max': undefined, - }, - }, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - const products = await this.publicGetProducts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"LBA/BTC", - // "baseAsset":"LBA", - // "quoteAsset":"BTC", - // "status":"Normal", - // "minNotional":"0.000625", - // "maxNotional":"6.25", - // "marginTradable":false, - // "commissionType":"Quote", - // "commissionReserveRate":"0.001", - // "tickSize":"0.000000001", - // "lotSize":"1" - // }, - // ] - // } - // - const cash = await this.publicGetCashProducts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"QTUM/BTC", - // "domain":"BTC", - // "tradingStartTime":1569506400000, - // "collapseDecimals":"0.0001,0.000001,0.00000001", - // "minQty":"0.000000001", - // "maxQty":"1000000000", - // "minNotional":"0.000625", - // "maxNotional":"12.5", - // "statusCode":"Normal", - // "statusMessage":"", - // "tickSize":"0.00000001", - // "useTick":false, - // "lotSize":"0.1", - // "useLot":false, - // "commissionType":"Quote", - // "commissionReserveRate":"0.001", - // "qtyScale":1, - // "priceScale":8, - // "notionalScale":4 - // } - // ] - // } - // - const futures = await this.publicGetFuturesContracts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"BTC-PERP", - // "tradingStartTime":1579701600000, - // "collapseDecimals":"1,0.1,0.01", - // "minQty":"0.000000001", - // "maxQty":"1000000000", - // "minNotional":"5", - // "maxNotional":"1000000", - // "statusCode":"Normal", - // "statusMessage":"", - // "tickSize":"0.25", - // "lotSize":"0.0001", - // "priceScale":2, - // "qtyScale":4, - // "notionalScale":2 - // } - // ] - // } - // - const productsData = this.safeValue (products, 'data', []); - const productsById = this.indexBy (productsData, 'symbol'); - const cashData = this.safeValue (cash, 'data', []); - const futuresData = this.safeValue (futures, 'data', []); - const cashAndFuturesData = this.arrayConcat (cashData, futuresData); - const cashAndFuturesById = this.indexBy (cashAndFuturesData, 'symbol'); - const dataById = this.deepExtend (productsById, cashAndFuturesById); - const ids = Object.keys (dataById); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const market = dataById[id]; - const baseId = this.safeString (market, 'baseAsset'); - const quoteId = this.safeString (market, 'quoteAsset'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), - }; - const status = this.safeString (market, 'status'); - const active = (status === 'Normal'); - const type = ('useLot' in market) ? 'spot' : 'future'; - const spot = (type === 'spot'); - const future = (type === 'future'); - let symbol = id; - if (!future) { - symbol = base + '/' + quote; - } - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'type': type, - 'spot': spot, - 'future': future, - 'active': active, - 'precision': precision, - 'limits': { - 'amount': { - 'min': this.safeFloat (market, 'minQty'), - 'max': this.safeFloat (market, 'maxQty'), - }, - 'price': { - 'min': this.safeFloat (market, 'tickSize'), - 'max': undefined, - }, - 'cost': { - 'min': this.safeFloat (market, 'minNotional'), - 'max': this.safeFloat (market, 'maxNotional'), - }, - }, - }); - } - return result; - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - // TODO: fee calculation here is incorrect, we need to support tiered fee calculation. - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - - async fetchAccounts (params = {}) { - let accountGroup = this.safeString (this.options, 'account-group'); - let response = undefined; - if (accountGroup === undefined) { - response = await this.privateGetInfo (params); - // - // { - // "code":0, - // "data":{ - // "email":"igor.kroitor@gmail.com", - // "accountGroup":8, - // "viewPermission":true, - // "tradePermission":true, - // "transferPermission":true, - // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"], - // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"], - // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"], - // "userUID":"U6491137460" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - accountGroup = this.safeString (data, 'accountGroup'); - this.options['account-group'] = accountGroup; - } - return [ - { - 'id': accountGroup, - 'type': undefined, - 'currency': undefined, - 'info': response, - }, - ]; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchBalance', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeString (account, 'id'); - const request = { - 'account-group': accountGroup, - }; - let method = 'accountCategoryGetBalance'; - if (accountCategory === 'futures') { - method = 'accountGroupGetFuturesCollateralBalance'; - } else { - request['account-category'] = accountCategory; - } - const response = await this[method] (this.extend (request, params)); - // - // cash - // - // { - // 'code': 0, - // 'data': [ - // { - // 'asset': 'BCHSV', - // 'totalBalance': '64.298000048', - // 'availableBalance': '64.298000048', - // }, - // ] - // } - // - // margin - // - // { - // 'code': 0, - // 'data': [ - // { - // 'asset': 'BCHSV', - // 'totalBalance': '64.298000048', - // 'availableBalance': '64.298000048', - // 'borrowed': '0', - // 'interest': '0', - // }, - // ] - // } - // - // futures - // - // { - // "code":0, - // "data":[ - // {"asset":"BTC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"9456.59"}, - // {"asset":"ETH","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"235.95"}, - // {"asset":"USDT","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"}, - // {"asset":"USDC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00035"}, - // {"asset":"PAX","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00045"}, - // {"asset":"USDTR","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"} - // ] - // } - // - const result = { 'info': response }; - const balances = this.safeValue (response, 'data', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - const response = await this.publicGetDepth (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "m":"depth-snapshot", - // "symbol":"BTC-PERP", - // "data":{ - // "ts":1590223998202, - // "seqnum":115444921, - // "asks":[ - // ["9207.5","18.2383"], - // ["9207.75","18.8235"], - // ["9208","10.7873"], - // ], - // "bids":[ - // ["9207.25","0.4009"], - // ["9207","0.003"], - // ["9206.5","0.003"], - // ] - // } - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const orderbook = this.safeValue (data, 'data', {}); - const timestamp = this.safeInteger (orderbook, 'ts'); - const result = this.parseOrderBook (orderbook, timestamp); - result['nonce'] = this.safeInteger (orderbook, 'seqnum'); - return result; - } - - parseTicker (ticker, market = undefined) { - // - // { - // "symbol":"QTUM/BTC", - // "open":"0.00016537", - // "close":"0.00019077", - // "high":"0.000192", - // "low":"0.00016537", - // "volume":"846.6", - // "ask":["0.00018698","26.2"], - // "bid":["0.00018408","503.7"], - // "type":"spot" - // } - // - const timestamp = undefined; - const marketId = this.safeString (ticker, 'symbol'); - let symbol = undefined; - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } else if (marketId !== undefined) { - const type = this.safeString (ticker, 'type'); - if (type === 'spot') { - const [ baseId, quoteId ] = marketId.split ('/'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - } - } - if ((symbol === undefined) && (market !== undefined)) { - symbol = market['symbol']; - } - const close = this.safeFloat (ticker, 'close'); - const bid = this.safeValue (ticker, 'bid', []); - const ask = this.safeValue (ticker, 'ask', []); - const open = this.safeFloat (ticker, 'open'); - let change = undefined; - let percentage = undefined; - let average = undefined; - if ((open !== undefined) && (close !== undefined)) { - change = close - open; - if (open > 0) { - percentage = change / open * 100; - } - average = this.sum (open, close) / 2; - } - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 0), - 'bidVolume': this.safeFloat (bid, 1), - 'ask': this.safeFloat (ask, 0), - 'askVolume': this.safeFloat (ask, 1), - 'vwap': undefined, - 'open': open, - 'close': close, - 'last': close, - 'previousClose': undefined, // previous day close - 'change': change, - 'percentage': percentage, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - const response = await this.publicGetTicker (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "symbol":"BTC-PERP", // or "BTC/USDT" - // "open":"9073", - // "close":"9185.75", - // "high":"9185.75", - // "low":"9185.75", - // "volume":"576.8334", - // "ask":["9185.75","15.5863"], - // "bid":["9185.5","0.003"], - // "type":"derivatives", // or "spot" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - return this.parseTicker (data, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const request = {}; - if (symbols !== undefined) { - const marketIds = this.marketIds (symbols); - request['symbol'] = marketIds.join (','); - } - const response = await this.publicGetTicker (this.extend (request, params)); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"QTUM/BTC", - // "open":"0.00016537", - // "close":"0.00019077", - // "high":"0.000192", - // "low":"0.00016537", - // "volume":"846.6", - // "ask":["0.00018698","26.2"], - // "bid":["0.00018408","503.7"], - // "type":"spot" - // } - // ] - // } - // - const data = this.safeValue (response, 'data', []); - return this.parseTickers (data, symbols); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "m":"bar", - // "s":"BTC/USDT", - // "data":{ - // "i":"1", - // "ts":1590228000000, - // "o":"9139.59", - // "c":"9131.94", - // "h":"9139.99", - // "l":"9121.71", - // "v":"25.20648" - // } - // } - // - const data = this.safeValue (ohlcv, 'data', {}); - return [ - this.safeInteger (data, 'ts'), - this.safeFloat (data, 'o'), - this.safeFloat (data, 'h'), - this.safeFloat (data, 'l'), - this.safeFloat (data, 'c'), - this.safeFloat (data, 'v'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - 'interval': this.timeframes[timeframe], - }; - // if since and limit are not specified - // the exchange will return just 1 last candle by default - const duration = this.parseTimeframe (timeframe); - const options = this.safeValue (this.options, 'fetchOHLCV', {}); - const defaultLimit = this.safeInteger (options, 'limit', 500); - if (since !== undefined) { - request['from'] = since; - if (limit === undefined) { - limit = defaultLimit; - } else { - limit = Math.min (limit, defaultLimit); - } - request['to'] = this.sum (since, limit * duration * 1000, 1); - } else if (limit !== undefined) { - request['n'] = limit; // max 500 - } - const response = await this.publicGetBarhist (this.extend (request, params)); - // - // { - // "code":0, - // "data":[ - // { - // "m":"bar", - // "s":"BTC/USDT", - // "data":{ - // "i":"1", - // "ts":1590228000000, - // "o":"9139.59", - // "c":"9131.94", - // "h":"9139.99", - // "l":"9121.71", - // "v":"25.20648" - // } - // } - // ] - // } - // - const data = this.safeValue (response, 'data', []); - return this.parseOHLCVs (data, market, timeframe, since, limit); - } - - parseTrade (trade, market = undefined) { - // - // public fetchTrades - // - // { - // "p":"9128.5", // price - // "q":"0.0030", // quantity - // "ts":1590229002385, // timestamp - // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade - // "seqnum":180143985289898554 - // } - // - const timestamp = this.safeInteger (trade, 'ts'); - const price = this.safeFloat2 (trade, 'price', 'p'); - const amount = this.safeFloat (trade, 'q'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } - const buyerIsMaker = this.safeValue (trade, 'bm', false); - const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; - const side = buyerIsMaker ? 'buy' : 'sell'; - let symbol = undefined; - if ((symbol === undefined) && (market !== undefined)) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'id': undefined, - 'order': undefined, - 'type': undefined, - 'takerOrMaker': makerOrTaker, - 'side': side, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - if (limit !== undefined) { - request['n'] = limit; // max 100 - } - const response = await this.publicGetTrades (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "m":"trades", - // "symbol":"BTC-PERP", - // "data":[ - // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554}, - // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587}, - // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043} - // ] - // } - // } - // - const records = this.safeValue (response, 'data', []); - const trades = this.safeValue (records, 'data', []); - return this.parseTrades (trades, market, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'PendingNew': 'open', - 'New': 'open', - 'PartiallyFilled': 'open', - 'Filled': 'closed', - 'Canceled': 'canceled', - 'Rejected': 'rejected', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - // - // createOrder - // - // { - // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", - // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", - // "orderType": "Market", - // "symbol": "BTC/USDT", - // "timestamp": 1573576916201 - // } - // - // fetchOrder, fetchOpenOrders, fetchClosedOrders - // - // { - // "symbol": "BTC/USDT", - // "price": "8131.22", - // "orderQty": "0.00082", - // "orderType": "Market", - // "avgPx": "7392.02", - // "cumFee": "0.005152238", - // "cumFilledQty": "0.00082", - // "errorCode": "", - // "feeAsset": "USDT", - // "lastExecTime": 1575953151764, - // "orderId": "a16eee20b6750866943712zWEDdAjt3", - // "seqNum": 2623469, - // "side": "Buy", - // "status": "Filled", - // "stopPrice": "", - // "execInst": "NULL_VAL" - // } - // - // { - // "ac": "FUTURES", - // "accountId": "testabcdefg", - // "avgPx": "0", - // "cumFee": "0", - // "cumQty": "0", - // "errorCode": "NULL_VAL", - // "execInst": "NULL_VAL", - // "feeAsset": "USDT", - // "lastExecTime": 1584072844085, - // "orderId": "r170d21956dd5450276356bbtcpKa74", - // "orderQty": "1.1499", - // "orderType": "Limit", - // "price": "4000", - // "sendingTime": 1584072841033, - // "seqNum": 24105338, - // "side": "Buy", - // "status": "Canceled", - // "stopPrice": "", - // "symbol": "BTC-PERP" - // }, - // - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'symbol'); - const symbol = this.safeSymbol (marketId, market, '/'); - let timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); - let lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const average = this.safeFloat (order, 'avgPx'); - const filled = this.safeFloat2 (order, 'cumFilledQty', 'cumQty'); - let remaining = undefined; - if (filled !== undefined) { - if (filled === 0) { - timestamp = lastTradeTimestamp; - lastTradeTimestamp = undefined; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - let cost = undefined; - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - const id = this.safeString (order, 'orderId'); - let clientOrderId = this.safeString (order, 'id'); - if (clientOrderId !== undefined) { - if (clientOrderId.length < 1) { - clientOrderId = undefined; - } - } - const type = this.safeStringLower (order, 'orderType'); - const side = this.safeStringLower (order, 'side'); - const feeCost = this.safeFloat (order, 'cumFee'); - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (order, 'feeAsset'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': stopPrice, - 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, - 'remaining': remaining, - 'status': status, - 'fee': fee, - 'trades': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const market = this.market (symbol); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'createOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'symbol': market['id'], - 'time': this.milliseconds (), - 'orderQty': this.amountToPrecision (symbol, amount), - 'orderType': type, // "limit", "market", "stop_market", "stop_limit" - 'side': side, // "buy" or "sell" - // 'orderPrice': this.priceToPrecision (symbol, price), - // 'stopPrice': this.priceToPrecision (symbol, stopPrice), // required for stop orders - // 'postOnly': 'false', // 'false', 'true' - // 'timeInForce': 'GTC', // GTC, IOC, FOK - // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE - }; - if (clientOrderId !== undefined) { - request['id'] = clientOrderId; - params = this.omit (params, [ 'clientOrderId', 'id' ]); - } - if ((type === 'limit') || (type === 'stop_limit')) { - request['orderPrice'] = this.priceToPrecision (symbol, price); - } - if ((type === 'stop_limit') || (type === 'stop_market')) { - const stopPrice = this.safeFloat (params, 'stopPrice'); - if (stopPrice === undefined) { - throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); - } else { - request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); - params = this.omit (params, 'stopPrice'); - } - } - const response = await this.accountCategoryPostOrder (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "ac": "MARGIN", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "action": "place-order", - // "info": { - // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", - // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", - // "orderType": "Market", - // "symbol": "BTC/USDT", - // "timestamp": 1573576916201 - // }, - // "status": "Ack" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const info = this.safeValue (data, 'info', {}); - return this.parseOrder (info, market); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'orderId': id, - }; - const response = await this.accountCategoryGetOrderStatus (this.extend (request, params)); - // - // { - // "code": 0, - // "accountCategory": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "data": [ - // { - // "symbol": "BTC/USDT", - // "price": "8131.22", - // "orderQty": "0.00082", - // "orderType": "Market", - // "avgPx": "7392.02", - // "cumFee": "0.005152238", - // "cumFilledQty": "0.00082", - // "errorCode": "", - // "feeAsset": "USDT", - // "lastExecTime": 1575953151764, - // "orderId": "a16eee20b6750866943712zWEDdAjt3", - // "seqNum": 2623469, - // "side": "Buy", - // "status": "Filled", - // "stopPrice": "", - // "execInst": "NULL_VAL" - // } - // ] - // } - // - const data = this.safeValue (response, 'data', {}); - return this.parseOrder (data); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchOpenOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - }; - const response = await this.accountCategoryGetOrderOpen (this.extend (request, params)); - // - // { - // "ac": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "code": 0, - // "data": [ - // { - // "avgPx": "0", // Average filled price of the order - // "cumFee": "0", // cumulative fee paid for this order - // "cumFilledQty": "0", // cumulative filled quantity - // "errorCode": "", // error code; could be empty - // "feeAsset": "USDT", // fee asset - // "lastExecTime": 1576019723550, // The last execution time of the order - // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId - // "orderQty": "0.0083", // order quantity - // "orderType": "Limit", // order type - // "price": "7105", // order price - // "seqNum": 8193258, // sequence number - // "side": "Buy", // order side - // "status": "New", // order status on matching engine - // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty - // "symbol": "BTC/USDT", - // "execInst": "NULL_VAL" // execution instruction - // }, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - if (accountCategory === 'futures') { - return this.parseOrders (data, market, since, limit); - } - // a workaround for https://github.com/ccxt/ccxt/issues/7187 - const orders = []; - for (let i = 0; i < data.length; i++) { - const order = this.parseOrder (data[i], market); - orders.push (order); - } - return this.filterBySymbolSinceLimit (orders, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - const defaultAccountCategory = this.safeString (this.options, 'account-category'); - const options = this.safeValue (this.options, 'fetchClosedOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - // 'category': accountCategory, - // 'symbol': market['id'], - // 'orderType': 'market', // optional, string - // 'side': 'buy', // or 'sell', optional, case insensitive. - // 'status': 'Filled', // "Filled", "Canceled", or "Rejected" - // 'startTime': exchange.milliseconds (), - // 'endTime': exchange.milliseconds (), - // 'page': 1, - // 'pageSize': 100, - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['symbol'] = market['id']; - } - const method = this.safeValue (options, 'method', 'accountGroupGetOrderHist'); - if (method === 'accountGroupGetOrderHist') { - if (accountCategory !== undefined) { - request['category'] = accountCategory; - } - } else { - request['account-category'] = accountCategory; - } - if (since !== undefined) { - request['startTime'] = since; - } - if (limit !== undefined) { - request['pageSize'] = limit; - } - const response = await this[method] (this.extend (request, params)); - // - // accountCategoryGetOrderHistCurrent - // - // { - // "code":0, - // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda", - // "ac":"CASH", - // "data":[ - // { - // "seqNum":15561826728, - // "orderId":"a17294d305c0U6491137460bethu7kw9", - // "symbol":"ETH/USDT", - // "orderType":"Limit", - // "lastExecTime":1591635618200, - // "price":"200", - // "orderQty":"0.1", - // "side":"Buy", - // "status":"Canceled", - // "avgPx":"0", - // "cumFilledQty":"0", - // "stopPrice":"", - // "errorCode":"", - // "cumFee":"0", - // "feeAsset":"USDT", - // "execInst":"NULL_VAL" - // } - // ] - // } - // - // accountGroupGetOrderHist - // - // { - // "code": 0, - // "data": { - // "data": [ - // { - // "ac": "FUTURES", - // "accountId": "testabcdefg", - // "avgPx": "0", - // "cumFee": "0", - // "cumQty": "0", - // "errorCode": "NULL_VAL", - // "execInst": "NULL_VAL", - // "feeAsset": "USDT", - // "lastExecTime": 1584072844085, - // "orderId": "r170d21956dd5450276356bbtcpKa74", - // "orderQty": "1.1499", - // "orderType": "Limit", - // "price": "4000", - // "sendingTime": 1584072841033, - // "seqNum": 24105338, - // "side": "Buy", - // "status": "Canceled", - // "stopPrice": "", - // "symbol": "BTC-PERP" - // }, - // ], - // "hasNext": False, - // "limit": 500, - // "page": 1, - // "pageSize": 20 - // } - // } - // - let data = this.safeValue (response, 'data'); - const isArray = Array.isArray (data); - if (!isArray) { - data = this.safeValue (data, 'data', []); - } - return this.parseOrders (data, market, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument'); - } - await this.loadMarkets (); - await this.loadAccounts (); - const market = this.market (symbol); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'cancelOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'symbol': market['id'], - 'time': this.milliseconds (), - 'id': 'foobar', - }; - if (clientOrderId === undefined) { - request['orderId'] = id; - } else { - request['id'] = clientOrderId; - params = this.omit (params, [ 'clientOrderId', 'id' ]); - } - const response = await this.accountCategoryDeleteOrder (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "ac": "CASH", - // "action": "cancel-order", - // "status": "Ack", - // "info": { - // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23", - // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc", - // "orderType": "", // could be empty - // "symbol": "ETH/USDT", - // "timestamp": 1573594877822 - // } - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const info = this.safeValue (data, 'info', {}); - return this.parseOrder (info, market); - } - - async cancelAllOrders (symbol = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'cancelAllOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'time': this.milliseconds (), - }; - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - request['symbol'] = market['id']; - } - const response = await this.accountCategoryDeleteOrderAll (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "ac": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "action": "cancel-all", - // "info": { - // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy", - // "orderId": "", - // "orderType": "NULL_VAL", - // "symbol": "", - // "timestamp": 1574118495462 - // }, - // "status": "Ack" - // } - // } - // - return response; - } - - parseDepositAddress (depositAddress, currency = undefined) { - // - // { - // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // destTag: "", - // tagType: "", - // tagId: "", - // chainName: "ERC20", - // numConfirmations: 20, - // withdrawalFee: 1, - // nativeScale: 4, - // tips: [] - // } - // - const address = this.safeString (depositAddress, 'address'); - const tagId = this.safeString (depositAddress, 'tagId'); - const tag = this.safeString (depositAddress, tagId); - this.checkAddress (address); - const code = (currency === undefined) ? undefined : currency['code']; - return { - 'currency': code, - 'address': address, - 'tag': tag, - 'info': depositAddress, - }; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const chainName = this.safeString (params, 'chainName'); - params = this.omit (params, 'chainName'); - const request = { - 'asset': currency['id'], - }; - const response = await this.privateGetWalletDepositAddress (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "asset":"USDT", - // "assetName":"Tether", - // "address":[ - // { - // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6", - // "destTag":"", - // "tagType":"", - // "tagId":"", - // "chainName":"Omni", - // "numConfirmations":3, - // "withdrawalFee":4.7, - // "nativeScale":4, - // "tips":[] - // }, - // { - // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // "destTag":"", - // "tagType":"", - // "tagId":"", - // "chainName":"ERC20", - // "numConfirmations":20, - // "withdrawalFee":1.0, - // "nativeScale":4, - // "tips":[] - // } - // ] - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const addresses = this.safeValue (data, 'address', []); - const numAddresses = addresses.length; - let address = undefined; - if (numAddresses > 1) { - const addressesByChainName = this.indexBy (addresses, 'chainName'); - if (chainName === undefined) { - const chainNames = Object.keys (addressesByChainName); - const chains = chainNames.join (', '); - throw new ArgumentsRequired (this.id + ' fetchDepositAddress returned more than one address, a chainName parameter is required, one of ' + chains); - } - address = this.safeValue (addressesByChainName, chainName, {}); - } else { - // first address - address = this.safeValue (addresses, 0, {}); - } - const result = this.parseDepositAddress (address, currency); - return this.extend (result, { - 'info': response, - }); - } - - async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { - const request = { - 'txType': 'deposit', - }; - return await this.fetchTransactions (code, since, limit, this.extend (request, params)); - } - - async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { - const request = { - 'txType': 'withdrawal', - }; - return await this.fetchTransactions (code, since, limit, this.extend (request, params)); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'asset': currency['id'], - // 'page': 1, - // 'pageSize': 20, - // 'startTs': this.milliseconds (), - // 'endTs': this.milliseconds (), - // 'txType': undefned, // deposit, withdrawal - }; - let currency = undefined; - if (code !== undefined) { - currency = this.currency (code); - request['asset'] = currency['id']; - } - if (since !== undefined) { - request['startTs'] = since; - } - if (limit !== undefined) { - request['pageSize'] = limit; - } - const response = await this.privateGetWalletTransactions (this.extend (request, params)); - // - // { - // code: 0, - // data: { - // data: [ - // { - // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", - // time: 1591606166000, - // asset: "USDT", - // transactionType: "deposit", - // amount: "25", - // commission: "0", - // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", - // status: "pending", - // numConfirmed: 8, - // numConfirmations: 20, - // destAddress: { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" } - // } - // ], - // page: 1, - // pageSize: 20, - // hasNext: false - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const transactions = this.safeValue (data, 'data', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - 'reviewing': 'pending', - 'pending': 'pending', - 'confirmed': 'ok', - 'rejected': 'rejected', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", - // time: 1591606166000, - // asset: "USDT", - // transactionType: "deposit", - // amount: "25", - // commission: "0", - // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", - // status: "pending", - // numConfirmed: 8, - // numConfirmations: 20, - // destAddress: { - // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // destTag: "..." // for currencies that have it - // } - // } - // - const id = this.safeString (transaction, 'requestId'); - const amount = this.safeFloat (transaction, 'amount'); - const destAddress = this.safeValue (transaction, 'destAddress', {}); - const address = this.safeString (destAddress, 'address'); - const tag = this.safeString (destAddress, 'destTag'); - const txid = this.safeString (transaction, 'networkTransactionId'); - const type = this.safeString (transaction, 'transactionType'); - const timestamp = this.safeInteger (transaction, 'time'); - const currencyId = this.safeString (transaction, 'asset'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'commission'); - return { - 'info': transaction, - 'id': id, - 'currency': code, - 'amount': amount, - 'address': address, - 'addressTo': address, - 'addressFrom': undefined, - 'tag': tag, - 'tagTo': tag, - 'tagFrom': undefined, - 'status': status, - 'type': type, - 'updated': undefined, - 'txid': txid, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'fee': { - 'currency': code, - 'cost': feeCost, - }, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = ''; - let query = params; - const accountCategory = (api === 'accountCategory'); - if (accountCategory || (api === 'accountGroup')) { - url += this.implodeParams ('/{account-group}', params); - query = this.omit (params, 'account-group'); - } - const request = this.implodeParams (path, query); - url += '/api/pro/' + this.version; - if (accountCategory) { - url += this.implodeParams ('/{account-category}', query); - query = this.omit (query, 'account-category'); - } - url += '/' + request; - query = this.omit (query, this.extractParams (path)); - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const timestamp = this.milliseconds ().toString (); - const payload = timestamp + '+' + request; - const hmac = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64'); - headers = { - 'x-auth-key': this.apiKey, - 'x-auth-timestamp': timestamp, - 'x-auth-signature': hmac, - }; - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - headers['Content-Type'] = 'application/json'; - body = this.json (query); - } - } - url = this.urls['api'] + url; - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - // - // {'code': 6010, 'message': 'Not enough balance.'} - // {'code': 60060, 'message': 'The order is already filled or canceled.'} - // {"code":2100,"message":"ApiKeyFailure"} - // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}} - // - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'message'); - const error = (code !== undefined) && (code !== '0'); - if (error || (message !== undefined)) { - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],38:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],38:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -26373,6 +26421,7 @@ module.exports = class bitmax extends Exchange { const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, BadRequest, DDoSProtection, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -26583,8 +26632,8 @@ module.exports = class bitmex extends Exchange { 'amount': undefined, 'price': undefined, }; - const lotSize = this.safeFloat (market, 'lotSize'); - const tickSize = this.safeFloat (market, 'tickSize'); + const lotSize = this.safeNumber (market, 'lotSize'); + const tickSize = this.safeNumber (market, 'tickSize'); if (lotSize !== undefined) { precision['amount'] = lotSize; } @@ -26598,7 +26647,7 @@ module.exports = class bitmex extends Exchange { }, 'price': { 'min': tickSize, - 'max': this.safeFloat (market, 'maxPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { 'min': undefined, @@ -26608,7 +26657,7 @@ module.exports = class bitmex extends Exchange { const limitField = (position === quote) ? 'cost' : 'amount'; limits[limitField] = { 'min': lotSize, - 'max': this.safeFloat (market, 'maxOrderQty'), + 'max': this.safeNumber (market, 'maxOrderQty'), }; result.push ({ 'id': id, @@ -26620,8 +26669,8 @@ module.exports = class bitmex extends Exchange { 'active': active, 'precision': precision, 'limits': limits, - 'taker': this.safeFloat (market, 'takerFee'), - 'maker': this.safeFloat (market, 'makerFee'), + 'taker': this.safeNumber (market, 'takerFee'), + 'maker': this.safeNumber (market, 'makerFee'), 'type': type, 'spot': false, 'swap': swap, @@ -26687,21 +26736,17 @@ module.exports = class bitmex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - let free = this.safeFloat (balance, 'availableMargin'); - let total = this.safeFloat (balance, 'marginBalance'); + let free = this.safeString (balance, 'availableMargin'); + let total = this.safeString (balance, 'marginBalance'); if (code === 'BTC') { - if (free !== undefined) { - free /= 100000000; - } - if (total !== undefined) { - total /= 100000000; - } + free = Precise.stringDiv (free, '1e8'); + total = Precise.stringDiv (total, '1e8'); } account['free'] = free; account['total'] = total; result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -26780,8 +26825,8 @@ module.exports = class bitmex extends Exchange { for (let i = 0; i < response.length; i++) { const order = response[i]; const side = (order['side'] === 'Sell') ? 'asks' : 'bids'; - const amount = this.safeFloat (order, 'size'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const price = this.safeNumber (order, 'price'); // https://github.com/ccxt/ccxt/issues/4926 // https://github.com/ccxt/ccxt/issues/4927 // the exchange sometimes returns null price in the orderbook @@ -26987,7 +27032,7 @@ module.exports = class bitmex extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'transactType')); const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount !== undefined) { amount = amount / 100000000; } @@ -26998,7 +27043,7 @@ module.exports = class bitmex extends Exchange { // for unrealized pnl and other transactions without a timestamp timestamp = 0; // see comments above } - let feeCost = this.safeFloat (item, 'fee', 0); + let feeCost = this.safeNumber (item, 'fee', 0); if (feeCost !== undefined) { feeCost = feeCost / 100000000; } @@ -27006,7 +27051,7 @@ module.exports = class bitmex extends Exchange { 'cost': feeCost, 'currency': code, }; - let after = this.safeFloat (item, 'walletBalance'); + let after = this.safeNumber (item, 'walletBalance'); if (after !== undefined) { after = after / 100000000; } @@ -27325,8 +27370,8 @@ module.exports = class bitmex extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const open = this.safeFloat (ticker, 'prevPrice24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'prevPrice24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; if (last !== undefined && open !== undefined) { @@ -27339,13 +27384,13 @@ module.exports = class bitmex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askPrice'), + 'ask': this.safeNumber (ticker, 'askPrice'), 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'vwap'), + 'vwap': this.safeNumber (ticker, 'vwap'), 'open': open, 'close': last, 'last': last, @@ -27353,8 +27398,8 @@ module.exports = class bitmex extends Exchange { 'change': change, 'percentage': percentage, 'average': this.sum (open, last) / 2, - 'baseVolume': this.safeFloat (ticker, 'homeNotional24h'), - 'quoteVolume': this.safeFloat (ticker, 'foreignNotional24h'), + 'baseVolume': this.safeNumber (ticker, 'homeNotional24h'), + 'quoteVolume': this.safeNumber (ticker, 'foreignNotional24h'), 'info': ticker, }; } @@ -27379,11 +27424,11 @@ module.exports = class bitmex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -27512,23 +27557,23 @@ module.exports = class bitmex extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat2 (trade, 'avgPx', 'price'); - const amount = this.safeFloat2 (trade, 'size', 'lastQty'); + const price = this.safeNumber2 (trade, 'avgPx', 'price'); + const amount = this.safeNumber2 (trade, 'size', 'lastQty'); const id = this.safeString (trade, 'trdMatchID'); const order = this.safeString (trade, 'orderID'); const side = this.safeStringLower (trade, 'side'); // price * amount doesn't work for all symbols (e.g. XBT, ETH) - let cost = this.safeFloat (trade, 'execCost'); + let cost = this.safeNumber (trade, 'execCost'); if (cost !== undefined) { cost = Math.abs (cost) / 100000000; } let fee = undefined; if ('execComm' in trade) { - let feeCost = this.safeFloat (trade, 'execComm'); + let feeCost = this.safeNumber (trade, 'execComm'); feeCost = feeCost / 100000000; const currencyId = this.safeString (trade, 'settlCurrency'); const feeCurrency = this.safeCurrencyCode (currencyId); - const feeRate = this.safeFloat (trade, 'commission'); + const feeRate = this.safeNumber (trade, 'commission'); fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -27630,33 +27675,19 @@ module.exports = class bitmex extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'transactTime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty', 0.0); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (amount - filled, 0.0); - } - } - const average = this.safeFloat (order, 'avgPx'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = average * filled; - } else if (price !== undefined) { - cost = price * filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty', 0.0); + const average = this.safeNumber (order, 'avgPx'); const id = this.safeString (order, 'orderID'); const type = this.safeStringLower (order, 'ordType'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'clOrdID'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'ParticipateDoNotInitiate'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -27671,14 +27702,14 @@ module.exports = class bitmex extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { @@ -27739,7 +27770,7 @@ module.exports = class bitmex extends Exchange { 'ordType': orderType, }; if ((orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched')) { - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPx or stopPrice parameter for the ' + orderType + ' order type'); } else { @@ -27856,7 +27887,7 @@ module.exports = class bitmex extends Exchange { return this.parseOrders (response, market); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPosition (params); // [ @@ -28051,7 +28082,7 @@ module.exports = class bitmex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],39:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],39:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -28382,7 +28413,7 @@ module.exports = class bitpanda extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; @@ -28455,9 +28486,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -28504,8 +28535,8 @@ module.exports = class bitpanda extends Exchange { const activeFeeTier = this.safeValue (response, 'active_fee_tier', {}); const result = { 'info': response, - 'maker': this.safeFloat (activeFeeTier, 'maker_fee'), - 'taker': this.safeFloat (activeFeeTier, 'taker_fee'), + 'maker': this.safeNumber (activeFeeTier, 'maker_fee'), + 'taker': this.safeNumber (activeFeeTier, 'taker_fee'), 'percentage': true, 'tierBased': true, }; @@ -28514,9 +28545,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -28554,27 +28585,27 @@ module.exports = class bitpanda extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last_price'); - const percentage = this.safeFloat (ticker, 'price_change_percentage'); - const change = this.safeFloat (ticker, 'price_change'); + const last = this.safeNumber (ticker, 'last_price'); + const percentage = this.safeNumber (ticker, 'price_change_percentage'); + const change = this.safeNumber (ticker, 'price_change'); let open = undefined; let average = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'best_bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -28759,11 +28790,11 @@ module.exports = class bitpanda extends Exchange { const volumeField = this.safeString (options, 'volume', 'total_amount'); return [ alignedTimestamp, - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -28849,21 +28880,21 @@ module.exports = class bitpanda extends Exchange { timestamp = this.parse8601 (this.safeString (trade, 'time')); } const side = this.safeStringLower2 (trade, 'side', 'taker_side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + let cost = this.safeNumber (trade, 'volume'); if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { cost = amount * price; } const marketId = this.safeString (trade, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (feeInfo, 'fee_amount'); + const feeCost = this.safeNumber (feeInfo, 'fee_amount'); let takerOrMaker = undefined; let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (feeInfo, 'fee_percentage'); + const feeRate = this.safeNumber (feeInfo, 'fee_percentage'); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, @@ -28946,11 +28977,11 @@ module.exports = class bitpanda extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -29204,12 +29235,12 @@ module.exports = class bitpanda extends Exchange { // } // const id = this.safeString (transaction, 'transaction_id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const currencyId = this.safeString (transaction, 'currency'); currency = this.safeCurrency (currencyId, currency); const status = 'ok'; // the exchange returns cleared transactions only - const feeCost = this.safeFloat2 (transaction, 'fee_amount', 'fee'); + const feeCost = this.safeNumber2 (transaction, 'fee_amount', 'fee'); let fee = undefined; const addressTo = this.safeString (transaction, 'recipient'); const tagTo = this.safeString (transaction, 'destination_tag'); @@ -29324,72 +29355,34 @@ module.exports = class bitpanda extends Exchange { // ] // } // - const rawTrades = this.safeValue (order, 'trades', []); - order = this.safeValue (order, 'order', order); - const id = this.safeString (order, 'order_id'); - const clientOrderId = this.safeString (order, 'client_id'); - const timestamp = this.parse8601 (this.safeString (order, 'time')); - let status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'instrument_code'); + const rawOrder = this.safeValue (order, 'order', order); + const id = this.safeString (rawOrder, 'order_id'); + const clientOrderId = this.safeString (rawOrder, 'client_id'); + const timestamp = this.parse8601 (this.safeString (rawOrder, 'time')); + const rawStatus = this.parseOrderStatus (this.safeString (rawOrder, 'status')); + const status = this.parseOrderStatus (rawStatus); + const marketId = this.safeString (rawOrder, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - if (status === undefined) { - if (remaining > 0) { - status = 'open'; - } else { - status = 'closed'; - } - } - } - } - const side = this.safeStringLower (order, 'side'); - const type = this.safeStringLower (order, 'type'); - const trades = this.parseTrades (rawTrades, market, undefined, undefined); - const fees = []; - const numTrades = trades.length; - let lastTradeTimestamp = undefined; - let tradeCost = undefined; - let tradeAmount = undefined; - if (numTrades > 0) { - lastTradeTimestamp = trades[0]['timestamp']; - tradeCost = 0; - tradeAmount = 0; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - fees.push (trade['fee']); - lastTradeTimestamp = Math.max (lastTradeTimestamp, trade['timestamp']); - tradeCost = this.sum (tradeCost, trade['cost']); - tradeAmount = this.sum (tradeAmount, trade['amount']); - } - } - let average = this.safeFloat (order, 'average_price'); - if (average === undefined) { - if ((tradeCost !== undefined) && (tradeAmount !== undefined) && (tradeAmount !== 0)) { - average = tradeCost / tradeAmount; - } - } - if (cost === undefined) { - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - } - const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'trigger_price'); - const postOnly = this.safeValue (order, 'is_post_only'); - const result = { + const price = this.safeNumber (rawOrder, 'price'); + const amount = this.safeNumber (rawOrder, 'amount'); + const filledString = this.safeString (rawOrder, 'filled_amount'); + const filled = this.parseNumber (filledString); + const side = this.safeStringLower (rawOrder, 'side'); + const type = this.safeStringLower (rawOrder, 'type'); + const timeInForce = this.parseTimeInForce (this.safeString (rawOrder, 'time_in_force')); + const stopPrice = this.safeNumber (rawOrder, 'trigger_price'); + const postOnly = this.safeValue (rawOrder, 'is_post_only'); + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'type': type, + }); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -29398,41 +29391,14 @@ module.exports = class bitpanda extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, // 'fee': undefined, 'trades': trades, - }; - const numFees = fees.length; - if (numFees > 0) { - if (numFees === 1) { - result['fee'] = fees[0]; - } else { - const feesByCurrency = this.groupBy (fees, 'currency'); - const feeCurrencies = Object.keys (feesByCurrency); - const numFeesByCurrency = feeCurrencies.length; - if (numFeesByCurrency === 1) { - const feeCurrency = feeCurrencies[0]; - const feeArray = this.safeValue (feesByCurrency, feeCurrency); - let feeCost = 0; - for (let i = 0; i < feeArray.length; i++) { - feeCost = this.sum (feeCost, feeArray[i]['cost']); - } - result['fee'] = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } else { - result['fees'] = fees; - } - } - } else { - result['fee'] = undefined; - } - return result; + }); } parseTimeInForce (timeInForce) { @@ -29466,7 +29432,7 @@ module.exports = class bitpanda extends Exchange { priceIsRequired = true; } if (uppercaseType === 'STOP') { - const triggerPrice = this.safeFloat (params, 'trigger_price'); + const triggerPrice = this.safeNumber (params, 'trigger_price'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a trigger_price param for ' + type + ' orders'); } @@ -29869,7 +29835,7 @@ module.exports = class bitpanda extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],40:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],40:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -30029,28 +29995,28 @@ module.exports = class bitso extends Exchange { const symbol = base + '/' + quote; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), - 'max': this.safeFloat (market, 'maximum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), + 'max': this.safeNumber (market, 'maximum_amount'), }, 'price': { - 'min': this.safeFloat (market, 'minimum_price'), - 'max': this.safeFloat (market, 'maximum_price'), + 'min': this.safeNumber (market, 'minimum_price'), + 'max': this.safeNumber (market, 'maximum_price'), }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), - 'max': this.safeFloat (market, 'maximum_value'), + 'min': this.safeNumber (market, 'minimum_value'), + 'max': this.safeNumber (market, 'maximum_value'), }, }; - const defaultPricePrecision = this.safeFloat (this.options['precision'], quote, this.options['defaultPrecision']); - const pricePrecision = this.safeFloat (market, 'tick_size', defaultPricePrecision); + const defaultPricePrecision = this.safeNumber (this.options['precision'], quote, this.options['defaultPrecision']); + const pricePrecision = this.safeNumber (market, 'tick_size', defaultPricePrecision); const precision = { - 'amount': this.safeFloat (this.options['precision'], base, this.options['defaultPrecision']), + 'amount': this.safeNumber (this.options['precision'], base, this.options['defaultPrecision']), 'price': pricePrecision, }; const fees = this.safeValue (market, 'fees', {}); const flatRate = this.safeValue (fees, 'flat_rate', {}); - const maker = this.safeFloat (flatRate, 'maker'); - const taker = this.safeFloat (flatRate, 'taker'); + const maker = this.safeNumber (flatRate, 'maker'); + const taker = this.safeNumber (flatRate, 'taker'); const feeTiers = this.safeValue (fees, 'structure', []); const fee = { 'taker': parseFloat (this.decimalToPrecision (taker / 100, ROUND, 0.00000001, TICK_SIZE)), @@ -30062,9 +30028,9 @@ module.exports = class bitso extends Exchange { const makerFees = []; for (let j = 0; j < feeTiers.length; j++) { const tier = feeTiers[j]; - const volume = this.safeFloat (tier, 'volume'); - const takerFee = this.safeFloat (tier, 'taker'); - const makerFee = this.safeFloat (tier, 'maker'); + const volume = this.safeNumber (tier, 'volume'); + const takerFee = this.safeNumber (tier, 'taker'); + const makerFee = this.safeNumber (tier, 'maker'); const takerFeeToPrecision = parseFloat (this.decimalToPrecision (takerFee / 100, ROUND, 0.00000001, TICK_SIZE)); const makerFeeToPrecision = parseFloat (this.decimalToPrecision (makerFee / 100, ROUND, 0.00000001, TICK_SIZE)); takerFees.push ([ volume, takerFeeToPrecision ]); @@ -30104,14 +30070,13 @@ module.exports = class bitso extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'locked'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -30133,22 +30098,22 @@ module.exports = class bitso extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'payload'); const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -30169,12 +30134,12 @@ module.exports = class bitso extends Exchange { const marketId = this.safeString (trade, 'book'); const symbol = this.safeSymbol (marketId, market, '_'); const side = this.safeString2 (trade, 'side', 'maker_side'); - let amount = this.safeFloat2 (trade, 'amount', 'major'); + let amount = this.safeNumber2 (trade, 'amount', 'major'); if (amount !== undefined) { amount = Math.abs (amount); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fees_amount'); + const feeCost = this.safeNumber (trade, 'fees_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fees_currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -30183,11 +30148,11 @@ module.exports = class bitso extends Exchange { 'currency': feeCurrency, }; } - let cost = this.safeFloat (trade, 'minor'); + let cost = this.safeNumber (trade, 'minor'); if (cost !== undefined) { cost = Math.abs (cost); } - const price = this.safeFloat (trade, 'price'); + const price = this.safeNumber (trade, 'price'); const orderId = this.safeString (trade, 'oid'); const id = this.safeString (trade, 'tid'); return { @@ -30288,17 +30253,11 @@ module.exports = class bitso extends Exchange { const symbol = this.safeSymbol (marketId, market, '_'); const orderType = this.safeString (order, 'type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'unfilled_amount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'unfilled_amount'); const clientOrderId = this.safeString (order, 'client_id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -30315,12 +30274,12 @@ module.exports = class bitso extends Exchange { 'amount': amount, 'cost': undefined, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = 25, params = {}) { @@ -30496,7 +30455,7 @@ module.exports = class bitso extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],41:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],41:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -30614,6 +30573,16 @@ module.exports = class bitstamp extends Exchange { 'usdc_address/', 'omg_withdrawal/', 'omg_address/', + 'dai_withdrawal/', + 'dai_address/', + 'knc_withdrawal/', + 'knc_address/', + 'mkr_withdrawal/', + 'mkr_address/', + 'zrx_withdrawal/', + 'zrx_address/', + 'gusd_withdrawal/', + 'gusd_address/', 'transfer-to-main/', 'transfer-from-main/', 'withdrawal-requests/', @@ -30748,13 +30717,15 @@ module.exports = class bitstamp extends Exchange { const symbolId = baseId + '_' + quoteId; const id = this.safeString (market, 'url_symbol'); const precision = { - 'amount': market['base_decimals'], - 'price': market['counter_decimals'], + 'amount': this.safeInteger (market, 'base_decimals'), + 'price': this.safeInteger (market, 'counter_decimals'), }; - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; // let [ cost, currency ] = market['minimum_order'].split (' '); - const active = (market['trading'] === 'Enabled'); + const trading = this.safeString (market, 'trading'); + const active = (trading === 'Enabled'); result.push ({ 'id': id, 'symbol': symbol, @@ -30798,7 +30769,7 @@ module.exports = class bitstamp extends Exchange { 'type': currencyType, 'name': name, 'active': true, - 'fee': this.safeFloat (description['fees']['funding']['withdraw'], code), + 'fee': this.safeNumber (description['fees']['funding']['withdraw'], code), 'precision': precision, 'limits': { 'amount': { @@ -30851,13 +30822,16 @@ module.exports = class bitstamp extends Exchange { quote = this.safeCurrencyCode (quote); const description = this.safeString (market, 'description'); const [ baseDescription, quoteDescription ] = description.split (' / '); - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; if (!(base in result)) { - result[base] = this.constructCurrencyObject (baseId, base, baseDescription, market['base_decimals'], undefined, market); + const baseDecimals = this.safeInteger (market, 'base_decimals'); + result[base] = this.constructCurrencyObject (baseId, base, baseDescription, baseDecimals, undefined, market); } if (!(quote in result)) { - result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, market['counter_decimals'], parseFloat (cost), market); + const counterDecimals = this.safeInteger (market, 'counter_decimals'); + result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, counterDecimals, parseFloat (cost), market); } } return result; @@ -30899,25 +30873,25 @@ module.exports = class bitstamp extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -30960,7 +30934,7 @@ module.exports = class bitstamp extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; if (id.indexOf ('_') < 0) { - const value = this.safeFloat (transaction, id); + const value = this.safeNumber (transaction, id); if ((value !== undefined) && (value !== 0)) { return id; } @@ -31042,11 +31016,11 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString2 (trade, 'id', 'tid'); let symbol = undefined; let side = undefined; - let price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat (trade, 'amount'); + let price = this.safeNumber (trade, 'price'); + let amount = this.safeNumber (trade, 'amount'); const orderId = this.safeString (trade, 'order_id'); const type = undefined; - let cost = this.safeFloat (trade, 'cost'); + let cost = this.safeNumber (trade, 'cost'); if (market === undefined) { const keys = Object.keys (trade); for (let i = 0; i < keys.length; i++) { @@ -31063,12 +31037,12 @@ module.exports = class bitstamp extends Exchange { market = this.getMarketFromTrade (trade); } } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = undefined; if (market !== undefined) { - price = this.safeFloat (trade, market['symbolId'], price); - amount = this.safeFloat (trade, market['baseId'], amount); - cost = this.safeFloat (trade, market['quoteId'], cost); + price = this.safeNumber (trade, market['symbolId'], price); + amount = this.safeNumber (trade, market['baseId'], amount); + cost = this.safeNumber (trade, market['quoteId'], cost); feeCurrency = market['quote']; symbol = market['symbol']; } @@ -31137,7 +31111,7 @@ module.exports = class bitstamp extends Exchange { parseTradingFee (balances, symbol) { const market = this.market (symbol); - const tradeFee = this.safeFloat (balances, market['id'] + '_fee'); + const tradeFee = this.safeNumber (balances, market['id'] + '_fee'); return { 'symbol': symbol, 'maker': tradeFee, @@ -31187,11 +31161,11 @@ module.exports = class bitstamp extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -31249,12 +31223,12 @@ module.exports = class bitstamp extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -31301,7 +31275,7 @@ module.exports = class bitstamp extends Exchange { if (id.indexOf ('_withdrawal_fee') >= 0) { const currencyId = id.split ('_')[0]; const code = this.safeCurrencyCode (currencyId); - withdraw[code] = this.safeFloat (balance, id); + withdraw[code] = this.safeNumber (balance, id); } } return { @@ -31547,16 +31521,16 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString (transaction, 'id'); const currencyId = this.getCurrencyIdFromTransaction (transaction); const code = this.safeCurrencyCode (currencyId, currency); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let feeCurrency = undefined; let amount = undefined; if ('amount' in transaction) { - amount = this.safeFloat (transaction, 'amount'); + amount = this.safeNumber (transaction, 'amount'); } else if (currency !== undefined) { - amount = this.safeFloat (transaction, currency['id'], amount); + amount = this.safeNumber (transaction, currency['id'], amount); feeCurrency = currency['code']; } else if ((code !== undefined) && (currencyId !== undefined)) { - amount = this.safeFloat (transaction, currencyId, amount); + amount = this.safeNumber (transaction, currencyId, amount); feeCurrency = code; } if (amount !== undefined) { @@ -31681,83 +31655,23 @@ module.exports = class bitstamp extends Exchange { } // there is no timestamp from fetchOrder const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - let lastTradeTimestamp = undefined; - let symbol = undefined; - let marketId = this.safeStringLower (order, 'currency_pair'); - if (marketId !== undefined) { - marketId = marketId.replace ('/', ''); - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - symbol = market['symbol']; - } - } - let amount = this.safeFloat (order, 'amount'); - let filled = 0.0; - const trades = []; - const transactions = this.safeValue (order, 'transactions', []); - let feeCost = undefined; - let cost = undefined; - const numTransactions = transactions.length; - if (numTransactions > 0) { - feeCost = 0.0; - for (let i = 0; i < numTransactions; i++) { - const trade = this.parseTrade (this.extend ({ - 'order_id': id, - 'side': side, - }, transactions[i]), market); - filled = this.sum (filled, trade['amount']); - feeCost = this.sum (feeCost, trade['fee']['cost']); - if (cost === undefined) { - cost = 0.0; - } - cost = this.sum (cost, trade['cost']); - trades.push (trade); - } - lastTradeTimestamp = trades[numTransactions - 1]['timestamp']; - } + const marketId = this.safeStringLower (order, 'currency_pair'); + let symbol = this.safeSymbol (marketId, market, '/'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((status === 'closed') && (amount === undefined)) { - amount = filled; + const amount = this.safeNumber (order, 'amount'); + const transactions = this.safeValue (order, 'transactions', []); + const trades = this.parseTrades (transactions, market); + const length = trades.length; + if (length) { + symbol = trades[0]['symbol']; } - let remaining = undefined; - if (amount !== undefined) { - remaining = amount - filled; - } - let price = this.safeFloat (order, 'price'); - if (market === undefined) { - market = this.getMarketFromTrades (trades); - } - let feeCurrency = undefined; - if (market !== undefined) { - if (symbol === undefined) { - symbol = market['symbol']; - } - feeCurrency = market['quote']; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if (price === undefined) { - if (filled > 0) { - price = cost / filled; - } - } - let fee = undefined; - if (feeCost !== undefined) { - if (feeCurrency !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { + const price = this.safeNumber (order, 'price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'status': status, 'symbol': symbol, 'type': undefined, @@ -31766,15 +31680,15 @@ module.exports = class bitstamp extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, - 'filled': filled, - 'remaining': remaining, + 'filled': undefined, + 'remaining': undefined, 'trades': trades, - 'fee': fee, + 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } parseLedgerEntryType (type) { @@ -31854,11 +31768,11 @@ module.exports = class bitstamp extends Exchange { const parsedTransaction = this.parseTransaction (item); let direction = undefined; if ('amount' in item) { - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); direction = amount > 0 ? 'in' : 'out'; } else if (('currency' in parsedTransaction) && parsedTransaction['currency'] !== undefined) { const currencyId = this.currencyId (parsedTransaction['currency']); - const amount = this.safeFloat (item, currencyId); + const amount = this.safeNumber (item, currencyId); direction = amount > 0 ? 'in' : 'out'; } return { @@ -32105,13 +32019,14 @@ module.exports = class bitstamp extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],42:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],42:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -32208,25 +32123,25 @@ module.exports = class bitstamp1 extends Exchange { await this.loadMarkets (); const ticker = await this.publicGetTicker (params); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -32249,14 +32164,11 @@ module.exports = class bitstamp1 extends Exchange { } } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -32300,12 +32212,12 @@ module.exports = class bitstamp1 extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -32406,7 +32318,7 @@ module.exports = class bitstamp1 extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],43:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],43:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -32414,6 +32326,7 @@ module.exports = class bitstamp1 extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, DDoSProtection, PermissionDenied, AddressPending, OnMaintenance, BadRequest, InvalidAddress } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -32689,7 +32602,7 @@ module.exports = class bittrex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeSize'), + 'min': this.safeNumber (market, 'minTradeSize'), 'max': undefined, }, 'price': { @@ -32717,11 +32630,11 @@ module.exports = class bittrex extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); const balance = indexed[currencyId]; - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -32781,7 +32694,7 @@ module.exports = class bittrex extends Exchange { const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); const precision = 8; // default precision, todo: fix "magic constants" - const fee = this.safeFloat (currency, 'txFee'); // todo: redesign + const fee = this.safeNumber (currency, 'txFee'); // todo: redesign const isActive = this.safeString (currency, 'status'); result[code] = { 'id': id, @@ -32842,17 +32755,17 @@ module.exports = class bittrex extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'updatedAt')); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const percentage = this.safeFloat (ticker, 'percentChange'); - const last = this.safeFloat (ticker, 'lastTradeRate'); + const percentage = this.safeNumber (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'lastTradeRate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidRate'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidRate'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askRate'), + 'ask': this.safeNumber (ticker, 'askRate'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -32862,8 +32775,8 @@ module.exports = class bittrex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -32976,21 +32889,18 @@ module.exports = class bittrex extends Exchange { const order = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'marketSymbol'); market = this.safeMarket (marketId, market, '-'); - let cost = undefined; - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'quantity'); - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = undefined; const isTaker = this.safeValue (trade, 'isTaker'); if (isTaker !== undefined) { takerOrMaker = isTaker ? 'taker' : 'maker'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -33060,11 +32970,11 @@ module.exports = class bittrex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'startsAt')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -33171,9 +33081,9 @@ module.exports = class bittrex extends Exchange { let cost = undefined; if (isCeilingLimit) { request['limit'] = this.priceToPrecision (symbol, price); - cost = this.safeFloat2 (params, 'ceiling', 'cost', amount); + cost = this.safeNumber2 (params, 'ceiling', 'cost', amount); } else if (isCeilingMarket) { - cost = this.safeFloat2 (params, 'ceiling', 'cost'); + cost = this.safeNumber2 (params, 'ceiling', 'cost'); if (cost === undefined) { if (price === undefined) { cost = amount; @@ -33332,7 +33242,7 @@ module.exports = class bittrex extends Exchange { // } // const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const address = this.safeString (transaction, 'cryptoAddress'); const txid = this.safeString (transaction, 'txId'); const updated = this.parse8601 (this.safeString (transaction, 'updatedAt')); @@ -33368,7 +33278,7 @@ module.exports = class bittrex extends Exchange { status = 'ok'; } } - let feeCost = this.safeFloat (transaction, 'txCost'); + let feeCost = this.safeNumber (transaction, 'txCost'); if (feeCost === undefined) { if (type === 'deposit') { // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge- @@ -33425,15 +33335,9 @@ module.exports = class bittrex extends Exchange { // } // const marketSymbol = this.safeString (order, 'marketSymbol'); - let symbol = undefined; - let feeCurrency = undefined; - if (marketSymbol !== undefined) { - const [ baseId, quoteId ] = marketSymbol.split ('-'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - feeCurrency = quote; - } + market = this.safeMarket (marketSymbol, market, '-'); + const symbol = market['symbol']; + const feeCurrency = market['quote']; const direction = this.safeStringLower (order, 'direction'); const createdAt = this.safeString (order, 'createdAt'); const updatedAt = this.safeString (order, 'updatedAt'); @@ -33446,32 +33350,15 @@ module.exports = class bittrex extends Exchange { } const timestamp = this.parse8601 (createdAt); const type = this.safeStringLower (order, 'type'); - const quantity = this.safeFloat (order, 'quantity'); - const limit = this.safeFloat (order, 'limit'); - const fillQuantity = this.safeFloat (order, 'fillQuantity'); - const commission = this.safeFloat (order, 'commission'); - const proceeds = this.safeFloat (order, 'proceeds'); - let average = undefined; - let remaining = undefined; - if (fillQuantity !== undefined) { - if (proceeds !== undefined) { - if (fillQuantity > 0) { - average = proceeds / fillQuantity; - } else if (proceeds === 0) { - average = 0; - } - } - if (quantity !== undefined) { - remaining = quantity - fillQuantity; - } - } - let status = this.safeStringLower (order, 'status'); - if ((status === 'closed') && (remaining !== undefined) && (remaining > 0)) { - status = 'canceled'; - } + const quantity = this.safeNumber (order, 'quantity'); + const limit = this.safeNumber (order, 'limit'); + const fillQuantity = this.safeNumber (order, 'fillQuantity'); + const commission = this.safeNumber (order, 'commission'); + const proceeds = this.safeNumber (order, 'proceeds'); + const status = this.safeStringLower (order, 'status'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'timestamp': timestamp, @@ -33485,10 +33372,10 @@ module.exports = class bittrex extends Exchange { 'price': limit, 'stopPrice': undefined, 'cost': proceeds, - 'average': average, + 'average': undefined, 'amount': quantity, 'filled': fillQuantity, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': { 'cost': commission, @@ -33496,7 +33383,7 @@ module.exports = class bittrex extends Exchange { }, 'info': order, 'trades': undefined, - }; + }); } parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { @@ -33545,9 +33432,9 @@ module.exports = class bittrex extends Exchange { 'side': this.safeString (order, 'side'), 'order': this.safeString (order, 'id'), 'type': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'average'), - 'amount': this.safeFloat (order, 'filled'), - 'cost': this.safeFloat (order, 'cost'), + 'price': this.safeNumber (order, 'average'), + 'amount': this.safeNumber (order, 'filled'), + 'cost': this.safeNumber (order, 'cost'), 'symbol': this.safeString (order, 'symbol'), 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -33839,7 +33726,7 @@ module.exports = class bittrex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],44:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],44:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -33847,6 +33734,7 @@ module.exports = class bittrex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -34148,7 +34036,7 @@ module.exports = class bitvavo extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minOrderInBaseAsset'), + 'min': this.safeNumber (market, 'minOrderInBaseAsset'), 'max': undefined, }, 'price': { @@ -34156,7 +34044,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderInQuoteAsset'), + 'min': this.safeNumber (market, 'minOrderInQuoteAsset'), 'max': undefined, }, }, @@ -34219,7 +34107,7 @@ module.exports = class bitvavo extends Exchange { 'code': code, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -34235,7 +34123,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMinAmount'), + 'min': this.safeNumber (currency, 'withdrawalMinAmount'), 'max': undefined, }, }, @@ -34292,14 +34180,14 @@ module.exports = class bitvavo extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); + const last = this.safeNumber (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -34311,12 +34199,12 @@ module.exports = class bitvavo extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': vwap, 'open': open, 'close': last, @@ -34332,14 +34220,6 @@ module.exports = class bitvavo extends Exchange { return result; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24h (params); @@ -34453,12 +34333,11 @@ module.exports = class bitvavo extends Exchange { // feeCurrency: 'EUR' // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'side'); const id = this.safeString2 (trade, 'id', 'fillId'); @@ -34469,7 +34348,7 @@ module.exports = class bitvavo extends Exchange { if (taker !== undefined) { takerOrMaker = taker ? 'taker' : 'maker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); @@ -34540,11 +34419,11 @@ module.exports = class bitvavo extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -34592,13 +34471,12 @@ module.exports = class bitvavo extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'inOrder'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'inOrder'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDepositAddress (code, params = {}) { @@ -34648,7 +34526,7 @@ module.exports = class bitvavo extends Exchange { if (price !== undefined) { cost = amount * price; } else { - cost = this.safeFloat2 (params, 'cost', 'amountQuote'); + cost = this.safeNumber2 (params, 'cost', 'amountQuote'); } if (cost !== undefined) { const precision = market['precision']['price']; @@ -34661,7 +34539,7 @@ module.exports = class bitvavo extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['amount'] = this.amountToPrecision (symbol, amount); } else if (isStopMarket || isStopLimit) { - let stopPrice = this.safeFloat2 (params, 'stopPrice', 'triggerAmount'); + let stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerAmount'); if (stopPrice === undefined) { if (isStopLimit) { throw new ArgumentsRequired (this.id + ' createOrder requires a stopPrice parameter for a ' + type + ' order'); @@ -34723,7 +34601,7 @@ module.exports = class bitvavo extends Exchange { await this.loadMarkets (); const market = this.market (symbol); let request = {}; - const amountRemaining = this.safeFloat (params, 'amountRemaining'); + const amountRemaining = this.safeNumber (params, 'amountRemaining'); params = this.omit (params, 'amountRemaining'); if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); @@ -34788,7 +34666,6 @@ module.exports = class bitvavo extends Exchange { throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument'); } await this.loadMarkets (); - await this.loadMarkets (); const market = this.market (symbol); const request = { 'orderId': id, @@ -35014,26 +34891,13 @@ module.exports = class bitvavo extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let remaining = this.safeFloat (order, 'amountRemaining'); - let filled = this.safeFloat (order, 'filledAmount'); - const remainingCost = this.safeFloat (order, 'remainingCost'); - if ((remainingCost !== undefined) && (remainingCost === 0.0)) { - remaining = 0; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - const cost = this.safeFloat (order, 'filledAmountQuote'); - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amountRemaining'); + const filled = this.safeNumber (order, 'filledAmount'); + const cost = this.safeNumber (order, 'filledAmountQuote'); let fee = undefined; - const feeCost = this.safeFloat (order, 'feePaid'); + const feeCost = this.safeNumber (order, 'feePaid'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -35042,32 +34906,24 @@ module.exports = class bitvavo extends Exchange { 'currency': feeCurrencyCode, }; } - let lastTradeTimestamp = undefined; - const rawTrades = this.safeValue (order, 'fills'); - let trades = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'symbol': symbol, - 'order': id, - 'side': side, - }); - const numTrades = trades.length; - if (numTrades > 0) { - const lastTrade = this.safeValue (trades, numTrades - 1); - lastTradeTimestamp = lastTrade['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'symbol': symbol, + 'order': id, + 'side': side, + 'type': type, + }); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = this.safeValue (order, 'postOnly'); // https://github.com/ccxt/ccxt/issues/8489 - const stopPrice = this.safeFloat (order, 'triggerPrice'); - return { + const stopPrice = this.safeNumber (order, 'triggerPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -35077,13 +34933,13 @@ module.exports = class bitvavo extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -35278,11 +35134,11 @@ module.exports = class bitvavo extends Exchange { const currencyId = this.safeString (transaction, 'symbol'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -35373,7 +35229,7 @@ module.exports = class bitvavo extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],45:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],45:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -35435,7 +35291,7 @@ module.exports = class bitz extends Exchange { 'assets': 'https://{hostname}', }, 'www': 'https://www.bitz.com', - 'doc': 'https://apidoc.bitz.com/en/', + 'doc': 'https://apidocv2.bitz.plus/en/', 'fees': 'https://www.bitz.com/fee?type=1', 'referral': 'https://u.bitz.com/register?invite_code=1429193', }, @@ -35452,6 +35308,11 @@ module.exports = class bitz extends Exchange { 'currencyRate', 'currencyCoinRate', 'coinRate', + 'getContractCoin', + 'getContractKline', + 'getContractOrderBook', + 'getContractTradesHistory', + 'getContractTickers', ], }, 'trade': { @@ -35464,6 +35325,10 @@ module.exports = class bitz extends Exchange { 'getUserNowEntrustSheet', // open orders 'getEntrustSheetInfo', // order 'depositOrWithdraw', // transactions + 'getCoinAddress', + 'getCoinAddressList', + 'marketTrade', + 'addEntrustSheetBatch', ], }, 'assets': { @@ -35471,6 +35336,20 @@ module.exports = class bitz extends Exchange { 'getUserAssets', ], }, + 'contract': { + 'post': [ + 'addContractTrade', + 'cancelContractTrade', + 'getContractActivePositions', + 'getContractAccountInfo', + 'getContractMyPositions', + 'getContractOrderResult', + 'getContractTradeResult', + 'getContractOrder', + 'getContractMyHistoryTrade', + 'getContractMyTrades', + ], + }, }, 'fees': { 'trading': { @@ -35657,8 +35536,8 @@ module.exports = class bitz extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTrade'), - 'max': this.safeFloat (market, 'maxTrade'), + 'min': this.safeNumber (market, 'minTrade'), + 'max': this.safeNumber (market, 'maxTrade'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -35707,12 +35586,12 @@ module.exports = class bitz extends Exchange { const currencyId = this.safeString (balance, 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lock'); - account['total'] = this.safeFloat (balance, 'num'); - account['free'] = this.safeFloat (balance, 'over'); + account['used'] = this.safeString (balance, 'lock'); + account['total'] = this.safeString (balance, 'num'); + account['free'] = this.safeString (balance, 'over'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTicker (ticker, market = undefined) { @@ -35742,8 +35621,8 @@ module.exports = class bitz extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'now'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'now'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -35754,22 +35633,22 @@ module.exports = class bitz extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': change, - 'percentage': this.safeFloat (ticker, 'priceChange24h'), + 'percentage': this.safeNumber (ticker, 'priceChange24h'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -35959,8 +35838,8 @@ module.exports = class bitz extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'p'); - const amount = this.safeFloat (trade, 'n'); + const price = this.safeNumber (trade, 'p'); + const amount = this.safeNumber (trade, 'n'); let cost = undefined; if (price !== undefined) { if (amount !== undefined) { @@ -36028,11 +35907,11 @@ module.exports = class bitz extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -36130,22 +36009,17 @@ module.exports = class bitz extends Exchange { if (side !== undefined) { side = (side === 'sale') ? 'sell' : 'buy'; } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'number'); - const remaining = this.safeFloat (order, 'numberOver'); - const filled = this.safeFloat (order, 'numberDeal'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'number'); + const remaining = this.safeNumber (order, 'numberOver'); + const filled = this.safeNumber (order, 'numberDeal'); let timestamp = this.safeInteger (order, 'timestamp'); if (timestamp === undefined) { timestamp = this.safeTimestamp (order, 'created'); } - let cost = this.safeFloat (order, 'orderTotalPrice'); - if (price !== undefined) { - if (filled !== undefined) { - cost = filled * price; - } - } + const cost = this.safeNumber (order, 'orderTotalPrice'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -36167,7 +36041,7 @@ module.exports = class bitz extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -36494,7 +36368,7 @@ module.exports = class bitz extends Exchange { const type = this.safeStringLower (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'network_fee'); + const feeCost = this.safeNumber (transaction, 'network_fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -36509,7 +36383,7 @@ module.exports = class bitz extends Exchange { 'address': this.safeString (transaction, 'wallet'), 'tag': this.safeString (transaction, 'memo'), 'type': type, - 'amount': this.safeFloat (transaction, 'number'), + 'amount': this.safeNumber (transaction, 'number'), 'currency': code, 'status': status, 'updated': timestamp, @@ -36661,12 +36535,13 @@ module.exports = class bitz extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],46:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],46:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -36745,17 +36620,19 @@ module.exports = class bl3p extends Exchange { const available = this.safeValue (wallet, 'available', {}); const balance = this.safeValue (wallet, 'balance', {}); const account = this.account (); - account['free'] = this.safeFloat (available, 'value'); - account['total'] = this.safeFloat (balance, 'value'); + account['free'] = this.safeString (available, 'value'); + account['total'] = this.safeString (balance, 'value'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { + const price = this.safeNumber (bidask, priceKey); + const size = this.safeNumber (bidask, amountKey); return [ - bidask[priceKey] / 100000.0, - bidask[amountKey] / 100000000.0, + price / 100000.0, + size / 100000000.0, ]; } @@ -36775,16 +36652,16 @@ module.exports = class bl3p extends Exchange { }; const ticker = await this.publicGetMarketTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -36794,7 +36671,7 @@ module.exports = class bl3p extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker['volume'], '24h'), + 'baseVolume': this.safeNumber (ticker['volume'], '24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -36803,20 +36680,13 @@ module.exports = class bl3p extends Exchange { parseTrade (trade, market = undefined) { const id = this.safeString (trade, 'trade_id'); const timestamp = this.safeInteger (trade, 'date'); - let price = this.safeFloat (trade, 'price_int'); - if (price !== undefined) { - price /= 100000.0; - } - let amount = this.safeFloat (trade, 'amount_int'); - if (amount !== undefined) { - amount /= 100000000.0; - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + let priceString = this.safeString (trade, 'price_int'); + priceString = Precise.stringDiv (priceString, '100000'); + let amountString = this.safeString (trade, 'amount_int'); + amountString = Precise.stringDiv (amountString, '100000000'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -36899,7 +36769,7 @@ module.exports = class bl3p extends Exchange { } }; -},{"./base/Exchange":6}],47:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],47:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -37065,8 +36935,8 @@ module.exports = class bleutrade extends Exchange { 'code': code, 'name': this.safeString (item, 'AssetLong'), 'active': this.safeValue (item, 'IsActive') && !this.safeValue (item, 'MaintenanceMode'), - 'fee': this.safeFloat (item, 'WithdrawTxFee'), - 'precision': this.safeFloat (item, 'DecimalPlaces'), + 'fee': this.safeNumber (item, 'WithdrawTxFee'), + 'precision': this.safeNumber (item, 'DecimalPlaces'), 'info': item, 'limits': this.limits, }; @@ -37118,7 +36988,7 @@ module.exports = class bleutrade extends Exchange { 'taker': this.fees['trading']['taker'], 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinTradeSize'), + 'min': this.safeNumber (market, 'MinTradeSize'), 'max': undefined, }, 'price': { @@ -37194,8 +37064,8 @@ module.exports = class bleutrade extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'TimeStamp')); const marketId = this.safeString (ticker, 'MarketName'); const symbol = this.safeSymbol (marketId, market, '_'); - const previous = this.safeFloat (ticker, 'PrevDay'); - const last = this.safeFloat (ticker, 'Last'); + const previous = this.safeNumber (ticker, 'PrevDay'); + const last = this.safeNumber (ticker, 'Last'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -37210,11 +37080,11 @@ module.exports = class bleutrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'High'), - 'low': this.safeFloat (ticker, 'Low'), - 'bid': this.safeFloat (ticker, 'Bid'), + 'high': this.safeNumber (ticker, 'High'), + 'low': this.safeNumber (ticker, 'Low'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': previous, @@ -37224,8 +37094,8 @@ module.exports = class bleutrade extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume'), - 'quoteVolume': this.safeFloat (ticker, 'BaseVolume'), + 'baseVolume': this.safeNumber (ticker, 'Volume'), + 'quoteVolume': this.safeNumber (ticker, 'BaseVolume'), 'info': ticker, }; } @@ -37233,11 +37103,11 @@ module.exports = class bleutrade extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (ohlcv['TimeStamp'] + '+00:00'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -37313,11 +37183,11 @@ module.exports = class bleutrade extends Exchange { const currencyId = this.safeString (item, 'Asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (item, 'Available'); - account['total'] = this.safeFloat (item, 'Balance'); + account['free'] = this.safeString (item, 'Available'); + account['total'] = this.safeString (item, 'Balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -37460,7 +37330,7 @@ module.exports = class bleutrade extends Exchange { // } const timestamp = this.parse8601 (this.safeString (item, 'TimeStamp')); - let amount = this.safeFloat (item, 'Amount'); + let amount = this.safeNumber (item, 'Amount'); let direction = undefined; if (amount !== undefined) { direction = 'in'; @@ -37534,27 +37404,12 @@ module.exports = class bleutrade extends Exchange { if ('Created' in order) { timestamp = this.parse8601 (order['Created'] + '+00:00'); } - let price = this.safeFloat (order, 'Price'); - let cost = undefined; - const amount = this.safeFloat (order, 'Quantity'); - const remaining = this.safeFloat (order, 'QuantityRemaining'); - let filled = undefined; - if (amount !== undefined && remaining !== undefined) { - filled = amount - remaining; - } - if (!cost) { - if (price && filled) { - cost = price * filled; - } - } - if (!price) { - if (cost && filled) { - price = cost / filled; - } - } - const average = this.safeFloat (order, 'PricePerUnit'); + const price = this.safeNumber (order, 'Price'); + const amount = this.safeNumber (order, 'Quantity'); + const remaining = this.safeNumber (order, 'QuantityRemaining'); + const average = this.safeNumber (order, 'PricePerUnit'); const id = this.safeString (order, 'OrderID'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -37568,15 +37423,15 @@ module.exports = class bleutrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -37613,7 +37468,7 @@ module.exports = class bleutrade extends Exchange { // Symbol: 'BTC' } // const id = this.safeString (transaction, 'ID'); - let amount = this.safeFloat (transaction, 'Amount'); + let amount = this.safeNumber (transaction, 'Amount'); let type = 'deposit'; if (amount < 0) { amount = Math.abs (amount); @@ -37715,13 +37570,14 @@ module.exports = class bleutrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],48:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],48:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -37902,11 +37758,11 @@ module.exports = class braziliex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': this.safeFloat (currency, 'txWithdrawalFee'), + 'fee': this.safeNumber (currency, 'txWithdrawalFee'), }, 'deposit': { 'active': canDeposit, - 'fee': this.safeFloat (currency, 'txDepositFee'), + 'fee': this.safeNumber (currency, 'txDepositFee'), }, }, 'limits': { @@ -37923,11 +37779,11 @@ module.exports = class braziliex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'MinWithdrawal'), + 'min': this.safeNumber (currency, 'MinWithdrawal'), 'max': Math.pow (10, precision), }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, }, @@ -37975,9 +37831,9 @@ module.exports = class braziliex extends Exchange { const quoteIsFiat = this.safeInteger (quoteCurrency, 'is_fiat', 0); let minCost = undefined; if (quoteIsFiat) { - minCost = this.safeFloat (baseCurrency, 'minAmountTradeFIAT'); + minCost = this.safeNumber (baseCurrency, 'minAmountTradeFIAT'); } else { - minCost = this.safeFloat (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); + minCost = this.safeNumber (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); } const isActive = this.safeInteger (market, 'active'); const active = (isActive === 1); @@ -38020,27 +37876,27 @@ module.exports = class braziliex extends Exchange { symbol = market['symbol']; } const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highestBid24'), - 'low': this.safeFloat (ticker, 'lowestAsk24'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'highestBid24'), + 'low': this.safeNumber (ticker, 'lowestAsk24'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'percentChange'), + 'change': this.safeNumber (ticker, 'percentChange'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume24'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume24'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24'), 'info': ticker, }; } @@ -38080,13 +37936,18 @@ module.exports = class braziliex extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString2 (trade, 'date_exec', 'date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } - const cost = this.safeFloat (trade, 'total'); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_number'); const type = 'limit'; const side = this.safeString (trade, 'type'); @@ -38128,11 +37989,11 @@ module.exports = class braziliex extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -38154,21 +38015,16 @@ module.exports = class braziliex extends Exchange { if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'date')); } - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'total', 0.0); - const amount = this.safeFloat (order, 'amount'); - const filledPercentage = this.safeFloat (order, 'progress'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'total'); + const amount = this.safeNumber (order, 'amount'); + const filledPercentage = this.safeNumber (order, 'progress'); const filled = amount * filledPercentage; - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); - let info = order; - if ('info' in info) { - info = order['info']; - } const id = this.safeString (order, 'order_number'); const fee = this.safeValue (order, 'fee'); // propagated from createOrder const status = (filledPercentage === 1.0) ? 'closed' : 'open'; const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -38185,12 +38041,12 @@ module.exports = class braziliex extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, - 'info': info, + 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -38242,7 +38098,7 @@ module.exports = class braziliex extends Exchange { 'price': this.safeString (priceParts, 1), 'total': this.safeString (totalParts, 1), 'fee': { - 'cost': this.safeFloat (feeParts, 1), + 'cost': this.safeNumber (feeParts, 1), 'currency': this.safeString (feeParts, 2), }, 'progress': '0.0', @@ -38359,13 +38215,14 @@ module.exports = class braziliex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],49:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],49:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, DDoSProtection, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -38507,8 +38364,8 @@ module.exports = class btcalpha extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -38560,14 +38417,11 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'id', 'tid'); const side = this.safeString2 (trade, 'my_side', 'side'); const orderId = this.safeString (trade, 'o_id'); @@ -38616,11 +38470,11 @@ module.exports = class btcalpha extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -38657,11 +38511,11 @@ module.exports = class btcalpha extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'reserve'); - account['total'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserve'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -38682,8 +38536,8 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (order, 'date'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString2 (order, 'oid', 'id'); let trades = this.safeValue (order, 'trades', []); @@ -38864,13 +38718,14 @@ module.exports = class btcalpha extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],50:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],50:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -38955,12 +38810,12 @@ module.exports = class btcbox extends Exchange { if (free in response) { const account = this.account (); const used = currencyId + '_lock'; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -38981,16 +38836,16 @@ module.exports = class btcbox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -39000,8 +38855,8 @@ module.exports = class btcbox extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -39025,14 +38880,11 @@ module.exports = class btcbox extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeString (trade, 'type'); return { @@ -39132,15 +38984,15 @@ module.exports = class btcbox extends Exchange { if (datetimeString !== undefined) { timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time } - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let cost = undefined; if (price !== undefined) { if (filled !== undefined) { @@ -39292,7 +39144,7 @@ module.exports = class btcbox extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],51:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],51:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -39541,11 +39393,11 @@ module.exports = class btcmarkets extends Exchange { const tagTo = tag; const addressFrom = undefined; const tagFrom = undefined; - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const currencyId = this.safeString (transaction, 'assetName'); const code = this.safeCurrencyCode (currencyId); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (fee) { amount -= fee; } @@ -39598,10 +39450,10 @@ module.exports = class btcmarkets extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const fees = this.safeValue (this.safeValue (this.options, 'fees', {}), quote, this.fees); - const pricePrecision = this.safeFloat (market, 'priceDecimals'); - const amountPrecision = this.safeFloat (market, 'amountDecimals'); - const minAmount = this.safeFloat (market, 'minOrderAmount'); - const maxAmount = this.safeFloat (market, 'maxOrderAmount'); + const pricePrecision = this.safeNumber (market, 'priceDecimals'); + const amountPrecision = this.safeNumber (market, 'amountDecimals'); + const minAmount = this.safeNumber (market, 'minOrderAmount'); + const maxAmount = this.safeNumber (market, 'maxOrderAmount'); let minPrice = undefined; if (quote === 'AUD') { minPrice = Math.pow (10, -pricePrecision); @@ -39660,14 +39512,12 @@ module.exports = class btcmarkets extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetName'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance, 'balance'); - const used = this.safeFloat (balance, 'locked'); const account = this.account (); - account['used'] = used; - account['total'] = total; + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -39683,11 +39533,11 @@ module.exports = class btcmarkets extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 0)), - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 2), // high - this.safeFloat (ohlcv, 3), // low - this.safeFloat (ohlcv, 4), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 2), // high + this.safeNumber (ohlcv, 3), // low + this.safeNumber (ohlcv, 4), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -39783,21 +39633,21 @@ module.exports = class btcmarkets extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'lastPrice'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); - const quoteVolume = this.safeFloat (ticker, 'volumeQte24h'); + const last = this.safeNumber (ticker, 'lastPrice'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); + const quoteVolume = this.safeNumber (ticker, 'volumeQte24h'); const vwap = this.vwap (baseVolume, quoteVolume); - const change = this.safeFloat (ticker, 'price24h'); - const percentage = this.safeFloat (ticker, 'pricePct24h'); + const change = this.safeNumber (ticker, 'price24h'); + const percentage = this.safeNumber (ticker, 'pricePct24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bestBid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'bestAsk'), + 'ask': this.safeNumber (ticker, 'bestAsk'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -39908,8 +39758,8 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -39918,7 +39768,7 @@ module.exports = class btcmarkets extends Exchange { } const orderId = this.safeString (trade, 'orderId'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -40009,7 +39859,7 @@ module.exports = class btcmarkets extends Exchange { } } if (triggerPriceIsRequired) { - const triggerPrice = this.safeFloat (params, 'triggerPrice'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); params = this.omit (params, 'triggerPrice'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a triggerPrice parameter for a ' + type + 'order'); @@ -40142,9 +39992,9 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const type = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'openAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'openAmount'); let filled = undefined; if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); @@ -40159,7 +40009,7 @@ module.exports = class btcmarkets extends Exchange { const id = this.safeString (order, 'orderId'); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -40351,13 +40201,14 @@ module.exports = class btcmarkets extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],52:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],52:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -40460,10 +40311,10 @@ module.exports = class btctradeua extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -40603,14 +40454,11 @@ module.exports = class btctradeua extends Exchange { const id = this.safeString (trade, 'id'); const type = 'limit'; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amnt_trade'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amnt_trade'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -40691,11 +40539,11 @@ module.exports = class btctradeua extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'amnt_trade'), + 'amount': this.safeNumber (order, 'amnt_trade'), 'filled': 0, - 'remaining': this.safeFloat (order, 'amnt_trade'), + 'remaining': this.safeNumber (order, 'amnt_trade'), 'trades': undefined, 'info': order, 'cost': undefined, @@ -40747,7 +40595,7 @@ module.exports = class btctradeua extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],53:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],53:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -40875,13 +40723,13 @@ module.exports = class btcturk extends Exchange { const used = currency['id'] + '_reserved'; if (free in response) { const account = this.account (); - account['free'] = this.safeFloat (response, free); - account['total'] = this.safeFloat (response, total); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['total'] = this.safeString (response, total); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -40901,26 +40749,26 @@ module.exports = class btcturk extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'average'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -40954,8 +40802,8 @@ module.exports = class btcturk extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -40997,11 +40845,11 @@ module.exports = class btcturk extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (this.safeString (ohlcv, 'Time')), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -41076,13 +40924,14 @@ module.exports = class btcturk extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],54:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],54:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -41299,7 +41148,7 @@ module.exports = class buda extends Exchange { } const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); - const precision = this.safeFloat (currency, 'input_decimals'); + const precision = this.safeNumber (currency, 'input_decimals'); const minimum = Math.pow (10, -precision); result[code] = { 'id': id, @@ -41460,24 +41309,25 @@ module.exports = class buda extends Exchange { let timestamp = undefined; let side = undefined; const type = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; const order = undefined; const fee = undefined; let symbol = undefined; - let cost = undefined; if (market) { symbol = market['symbol']; } if (Array.isArray (trade)) { - timestamp = parseInt (trade[0]); - price = parseFloat (trade[1]); - amount = parseFloat (trade[2]); - cost = price * amount; - side = trade[3]; - id = trade[4].toString (); + timestamp = this.safeInteger (trade, 0); + priceString = this.safeString (trade, 1); + amountString = this.safeString (trade, 2); + side = this.safeString (trade, 3); + id = this.safeString (trade, 4); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': order, @@ -41532,11 +41382,11 @@ module.exports = class buda extends Exchange { const currencyId = this.safeString (balance, 'id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = parseFloat (balance['available_amount'][0]); - account['total'] = parseFloat (balance['amount'][0]); + account['free'] = this.safeString (balance['available_amount'], 0); + account['total'] = this.safeString (balance['amount'], 0); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -41644,15 +41494,15 @@ module.exports = class buda extends Exchange { const side = this.safeStringLower (order, 'type'); const status = this.parseOrderStatus (this.safeString (order, 'state')); const originalAmount = this.safeValue (order, 'original_amount', []); - const amount = this.safeFloat (originalAmount, 0); + const amount = this.safeNumber (originalAmount, 0); const remainingAmount = this.safeValue (order, 'amount', []); - const remaining = this.safeFloat (remainingAmount, 0); + const remaining = this.safeNumber (remainingAmount, 0); const tradedAmount = this.safeValue (order, 'traded_amount', []); - const filled = this.safeFloat (tradedAmount, 0); + const filled = this.safeNumber (tradedAmount, 0); const totalExchanged = this.safeValue (order, 'totalExchanged', []); - const cost = this.safeFloat (totalExchanged, 0); + const cost = this.safeNumber (totalExchanged, 0); const limitPrice = this.safeValue (order, 'limit', []); - let price = this.safeFloat (limitPrice, 0); + let price = this.safeNumber (limitPrice, 0); if (price === undefined) { if (limitPrice !== undefined) { price = limitPrice; @@ -41663,7 +41513,7 @@ module.exports = class buda extends Exchange { average = this.priceToPrecision (symbol, cost / filled); } const paidFee = this.safeValue (order, 'paid_fee', []); - const feeCost = this.safeFloat (paidFee, 0); + const feeCost = this.safeNumber (paidFee, 0); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (paidFee, 1); @@ -41902,13 +41752,14 @@ module.exports = class buda extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],55:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],55:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { RateLimitExceeded, BadSymbol, OrderNotFound, ExchangeError, AuthenticationError, ArgumentsRequired, ExchangeNotAvailable } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -42090,7 +41941,7 @@ module.exports = class bw extends Exchange { const symbol = base + '/' + quote; const state = this.safeInteger (market, 'state'); const active = (state === 1); - const fee = this.safeFloat (market, 'defaultFee'); + const fee = this.safeNumber (market, 'defaultFee'); result.push ({ 'id': id, 'active': active, @@ -42111,7 +41962,7 @@ module.exports = class bw extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -42197,11 +42048,11 @@ module.exports = class bw extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'drawFee'), + 'fee': this.safeNumber (currency, 'drawFee'), 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'limitAmount', 0), + 'min': this.safeNumber (currency, 'limitAmount', 0), 'max': undefined, }, 'price': { @@ -42214,7 +42065,7 @@ module.exports = class bw extends Exchange { }, 'withdraw': { 'min': undefined, - 'max': this.safeFloat (currency, 'onceDrawLimit'), + 'max': this.safeNumber (currency, 'onceDrawLimit'), }, }, }; @@ -42251,9 +42102,9 @@ module.exports = class bw extends Exchange { 'high': parseFloat (this.safeValue (ticker, 2)), 'low': parseFloat (this.safeValue (ticker, 3)), 'bid': parseFloat (this.safeValue (ticker, 7)), - 'bidVolume': this.safeFloat (bid, 'quantity'), + 'bidVolume': this.safeNumber (bid, 'quantity'), 'ask': parseFloat (this.safeValue (ticker, 8)), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, 'open': undefined, 'close': close, @@ -42382,8 +42233,11 @@ module.exports = class bw extends Exchange { // ... // const timestamp = this.safeTimestamp (trade, 2); - const price = this.safeFloat (trade, 5); - const amount = this.safeFloat (trade, 6); + const priceString = this.safeString (trade, 5); + const amountString = this.safeString (trade, 6); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 1); let symbol = undefined; if (marketId !== undefined) { @@ -42400,12 +42254,6 @@ module.exports = class bw extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const sideString = this.safeString (trade, 4); const side = (sideString === 'ask') ? 'sell' : 'buy'; return { @@ -42419,7 +42267,7 @@ module.exports = class bw extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': parseFloat (cost), + 'cost': cost, 'fee': undefined, 'info': trade, }; @@ -42476,11 +42324,11 @@ module.exports = class bw extends Exchange { // return [ this.safeTimestamp (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - this.safeFloat (ohlcv, 6), - this.safeFloat (ohlcv, 7), - this.safeFloat (ohlcv, 8), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + this.safeNumber (ohlcv, 6), + this.safeNumber (ohlcv, 7), + this.safeNumber (ohlcv, 8), ]; } @@ -42538,11 +42386,11 @@ module.exports = class bw extends Exchange { const currencyId = this.safeString (balance, 'currencyTypeId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'amount'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'amount'); + account['used'] = this.safeString (balance, 'freeze'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -42638,25 +42486,13 @@ module.exports = class bw extends Exchange { } else if (side === '1') { side = 'buy'; } - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'completeAmount'); - let remaining = this.safeFloat2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available - let cost = this.safeFloat (order, 'totalMoney'); - if (filled !== undefined) { - if (amount !== undefined) { - if (remaining === undefined) { - remaining = amount - filled; - } - } - if (cost === undefined) { - if (price !== undefined) { - cost = filled * cost; - } - } - } + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'completeAmount'); + const remaining = this.safeNumber2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available + const cost = this.safeNumber (order, 'totalMoney'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'entrustId'), 'clientOrderId': undefined, @@ -42678,7 +42514,7 @@ module.exports = class bw extends Exchange { 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -42974,12 +42810,12 @@ module.exports = class bw extends Exchange { code = currency['code']; } const type = ('depositId' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat2 (transaction, 'actuallyAmount', 'amount'); + const amount = this.safeNumber2 (transaction, 'actuallyAmount', 'amount'); const status = this.parseTransactionStatus (this.safeString2 (transaction, 'verifyStatus', 'state')); const timestamp = this.safeInteger (transaction, 'createTime'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -43110,7 +42946,7 @@ module.exports = class bw extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],56:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],56:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -43155,6 +42991,7 @@ module.exports = class bybit extends Exchange { 'fetchTrades': true, 'fetchTransactions': false, 'fetchWithdrawals': true, + 'fetchPositions': true, }, 'timeframes': { '1m': '1', @@ -43186,6 +43023,34 @@ module.exports = class bybit extends Exchange { 'referral': 'https://www.bybit.com/app/register?ref=X7Prm', }, 'api': { + 'futures': { + 'private': { + 'get': [ + 'position/list', + 'order/list', + 'order', + 'stop-order/list', + 'stop-order', + 'execution/list', + 'trade/closed-pnl/list', + ], + 'post': [ + 'order/create', + 'order/cancel', + 'order/cancelAll', + 'order/replace', + 'stop-order/create', + 'stop-order/cancel', + 'stop-order/cancelAll', + 'stop-order/replace', + 'position/change-position-margin', + 'position/trading-stop', + 'position/leverage/save', + 'position/switch-mode', + 'position/switch-isolated', + ], + }, + }, 'v2': { 'public': { 'get': [ @@ -43399,7 +43264,11 @@ module.exports = class bybit extends Exchange { 'LTC/USDT': 'linear', 'XTZ/USDT': 'linear', 'LINK/USDT': 'linear', + 'ADA/USDT': 'linear', + 'DOT/USDT': 'linear', + 'UNI/USDT': 'linear', }, + 'defaultType': 'linear', // may also be inverse or inverseFuture 'code': 'BTC', 'cancelAllOrders': { // 'method': 'v2PrivatePostOrderCancelAll', // v2PrivatePostStopOrderCancelAll @@ -43514,8 +43383,8 @@ module.exports = class bybit extends Exchange { const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {}); const priceFilter = this.safeValue (market, 'price_filter', {}); const precision = { - 'amount': this.safeFloat (lotSizeFilter, 'qty_step'), - 'price': this.safeFloat (priceFilter, 'tick_size'), + 'amount': this.safeNumber (lotSizeFilter, 'qty_step'), + 'price': this.safeNumber (priceFilter, 'tick_size'), }; const status = this.safeString (market, 'status'); let active = undefined; @@ -43529,8 +43398,8 @@ module.exports = class bybit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'type': 'future', 'spot': false, 'future': true, @@ -43539,12 +43408,12 @@ module.exports = class bybit extends Exchange { 'inverse': inverse, 'limits': { 'amount': { - 'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'), - 'max': this.safeFloat (lotSizeFilter, 'max_trading_qty'), + 'min': this.safeNumber (lotSizeFilter, 'min_trading_qty'), + 'max': this.safeNumber (lotSizeFilter, 'max_trading_qty'), }, 'price': { - 'min': this.safeFloat (priceFilter, 'min_price'), - 'max': this.safeFloat (priceFilter, 'max_price'), + 'min': this.safeNumber (priceFilter, 'min_price'), + 'max': this.safeNumber (priceFilter, 'max_price'), }, 'cost': { 'min': undefined, @@ -43590,9 +43459,9 @@ module.exports = class bybit extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const open = this.safeFloat (ticker, 'prev_price_24h'); - let percentage = this.safeFloat (ticker, 'price_24h_pcnt'); + const last = this.safeNumber (ticker, 'last_price'); + const open = this.safeNumber (ticker, 'prev_price_24h'); + let percentage = this.safeNumber (ticker, 'price_24h_pcnt'); if (percentage !== undefined) { percentage *= 100; } @@ -43602,18 +43471,18 @@ module.exports = class bybit extends Exchange { change = last - open; average = this.sum (open, last) / 2; } - const baseVolume = this.safeFloat (ticker, 'turnover_24h'); - const quoteVolume = this.safeFloat (ticker, 'volume_24h'); + const baseVolume = this.safeNumber (ticker, 'turnover_24h'); + const quoteVolume = this.safeNumber (ticker, 'volume_24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price_24h'), - 'low': this.safeFloat (ticker, 'low_price_24h'), - 'bid': this.safeFloat (ticker, 'bid_price'), + 'high': this.safeNumber (ticker, 'high_price_24h'), + 'low': this.safeNumber (ticker, 'low_price_24h'), + 'bid': this.safeNumber (ticker, 'bid_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask_price'), + 'ask': this.safeNumber (ticker, 'ask_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -43762,11 +43631,11 @@ module.exports = class bybit extends Exchange { // return [ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat2 (ohlcv, 'turnover', 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber2 (ohlcv, 'turnover', 'volume'), ]; } @@ -43892,9 +43761,9 @@ module.exports = class bybit extends Exchange { const marketId = this.safeString (trade, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat2 (trade, 'qty', 'exec_qty'); - let cost = this.safeFloat (trade, 'exec_value'); - const price = this.safeFloat2 (trade, 'exec_price', 'price'); + const amount = this.safeNumber2 (trade, 'qty', 'exec_qty'); + let cost = this.safeNumber (trade, 'exec_value'); + const price = this.safeNumber2 (trade, 'exec_price', 'price'); if (cost === undefined) { if (amount !== undefined) { if (price !== undefined) { @@ -43909,14 +43778,14 @@ module.exports = class bybit extends Exchange { const side = this.safeStringLower (trade, 'side'); const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind'); const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker'; - const feeCost = this.safeFloat (trade, 'exec_fee'); + const feeCost = this.safeNumber (trade, 'exec_fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyCode = market['inverse'] ? market['base'] : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'fee_rate'), + 'rate': this.safeNumber (trade, 'fee_rate'), }; } return { @@ -44076,12 +43945,12 @@ module.exports = class bybit extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['used'] = this.safeFloat (balance, 'used_margin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'used_margin'); + account['total'] = this.safeString (balance, 'equity'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -44208,56 +44077,42 @@ module.exports = class bybit extends Exchange { // const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); - let symbol = undefined; - let base = undefined; + const symbol = market['symbol']; + let feeCurrency = undefined; const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const id = this.safeString2 (order, 'order_id', 'stop_order_id'); const type = this.safeStringLower (order, 'order_type'); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - let average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'qty'); - let cost = this.safeFloat (order, 'cum_exec_value'); - let filled = this.safeFloat (order, 'cum_exec_qty'); - let remaining = this.safeFloat (order, 'leaves_qty'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'qty'); + const cost = this.safeNumber (order, 'cum_exec_value'); + const filled = this.safeNumber (order, 'cum_exec_qty'); + const remaining = this.safeNumber (order, 'leaves_qty'); + const marketTypes = this.safeValue (this.options, 'marketTypes', {}); + const marketType = this.safeString (marketTypes, symbol); if (market !== undefined) { - symbol = market['symbol']; - base = market['base']; + if (marketType === 'linear') { + feeCurrency = market['quote']; + } else { + feeCurrency = market['base']; + } } let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time'); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = amount - remaining; - } - if (filled !== undefined) { - if ((remaining === undefined) && (amount !== undefined)) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if ((type === 'market') && (cost !== undefined) && (cost > 0)) { - price = undefined; - if (average === undefined) { - average = filled / cost; - } - } - } const status = this.parseOrderStatus (this.safeString2 (order, 'order_status', 'stop_order_status')); const side = this.safeStringLower (order, 'side'); - let feeCost = this.safeFloat (order, 'cum_exec_fee'); + let feeCost = this.safeNumber (order, 'cum_exec_fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); fee = { 'cost': feeCost, - 'currency': base, + 'currency': feeCurrency, }; } let clientOrderId = this.safeString (order, 'order_link_id'); @@ -44265,9 +44120,9 @@ module.exports = class bybit extends Exchange { clientOrderId = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'stop_px'); + const stopPrice = this.safeNumber (order, 'stop_px'); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -44289,7 +44144,7 @@ module.exports = class bybit extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -45140,7 +44995,8 @@ module.exports = class bybit extends Exchange { const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); + const type = this.safeStringLower (transaction, 'type'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -45160,8 +45016,8 @@ module.exports = class bybit extends Exchange { 'tag': undefined, 'tagTo': undefined, 'tagFrom': undefined, - 'type': 'withdrawal', - 'amount': this.safeFloat (transaction, 'amount'), + 'type': type, + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -45244,8 +45100,8 @@ module.exports = class bybit extends Exchange { // const currencyId = this.safeString (item, 'coin'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'wallet_balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'wallet_balance'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -45311,7 +45167,8 @@ module.exports = class bybit extends Exchange { 'recv_window': this.options['recvWindow'], 'timestamp': timestamp, }); - const auth = this.rawencode (this.keysort (query)); + const sortedQuery = this.keysort (query); + const auth = this.rawencode (sortedQuery); const signature = this.hmac (this.encode (auth), this.encode (this.secret)); if (method === 'POST') { body = this.json (this.extend (query, { @@ -45321,7 +45178,7 @@ module.exports = class bybit extends Exchange { 'Content-Type': 'application/json', }; } else { - request += '?' + auth + '&sign=' + signature; + request += '?' + this.urlencode (sortedQuery) + '&sign=' + signature; } } url += request; @@ -45344,17 +45201,48 @@ module.exports = class bybit extends Exchange { // time_now: '1583934106.590436' // } // - const errorCode = this.safeValue (response, 'ret_code'); - if (errorCode !== 0) { + const errorCode = this.safeString (response, 'ret_code'); + if (errorCode !== '0') { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback); this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback); throw new ExchangeError (feedback); // unknown message } } + + async fetchPositions (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (Array.isArray (symbols)) { + const length = symbols.length; + if (length !== 1) { + throw new ArgumentsRequired (this.id + ' fetchPositions takes exactly one symbol'); + } + request['symbol'] = this.marketId (symbols[0]); + } + const defaultType = this.safeString (this.options, 'defaultType', 'linear'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + let response = undefined; + if (type === 'linear') { + response = await this.privateLinearGetPositionList (this.extend (request, params)); + } else if (type === 'inverse') { + response = await this.v2PrivateGetPositionList (this.extend (request, params)); + } else if (type === 'inverseFuture') { + response = await this.futuresPrivateGetPositionList (this.extend (request, params)); + } + // { + // ret_code: 0, + // ret_msg: 'OK', + // ext_code: '', + // ext_info: '', + // result: [] or {} depending on the request + // } + return this.safeValue (response, 'result'); + } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],57:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],57:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -45543,12 +45431,12 @@ module.exports = class bytetrade extends Exchange { const limits = this.safeValue (currency, 'limits'); const deposit = this.safeValue (limits, 'deposit'); const amountPrecision = this.safeInteger (currency, 'basePrecision'); - let maxDeposit = this.safeFloat (deposit, 'max'); + let maxDeposit = this.safeNumber (deposit, 'max'); if (maxDeposit === -1.0) { maxDeposit = undefined; } const withdraw = this.safeValue (limits, 'withdraw'); - let maxWithdraw = this.safeFloat (withdraw, 'max'); + let maxWithdraw = this.safeNumber (withdraw, 'max'); if (maxWithdraw === -1.0) { maxWithdraw = undefined; } @@ -45564,11 +45452,11 @@ module.exports = class bytetrade extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (deposit, 'min'), + 'min': this.safeNumber (deposit, 'min'), 'max': maxDeposit, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'min'), + 'min': this.safeNumber (withdraw, 'min'), 'max': maxWithdraw, }, }, @@ -45622,12 +45510,12 @@ module.exports = class bytetrade extends Exchange { 'normalSymbol': normalSymbol, 'limits': { 'amount': { - 'min': this.safeFloat (amount, 'min'), - 'max': this.safeFloat (amount, 'max'), + 'min': this.safeNumber (amount, 'min'), + 'max': this.safeNumber (amount, 'max'), }, 'price': { - 'min': this.safeFloat (price, 'min'), - 'max': this.safeFloat (price, 'max'), + 'min': this.safeNumber (price, 'min'), + 'max': this.safeNumber (price, 'max'), }, 'cost': { 'min': undefined, @@ -45655,11 +45543,11 @@ module.exports = class bytetrade extends Exchange { const currencyId = this.safeString (balance, 'code'); const code = this.safeCurrencyCode (currencyId, undefined); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'used'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'used'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -45720,22 +45608,22 @@ module.exports = class bytetrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'open'), - 'close': this.safeFloat (ticker, 'close'), - 'last': this.safeFloat (ticker, 'last'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'open'), + 'close': this.safeNumber (ticker, 'close'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, // previous day close - 'change': this.safeFloat (ticker, 'change'), - 'percentage': this.safeFloat (ticker, 'percentage'), + 'change': this.safeNumber (ticker, 'change'), + 'percentage': this.safeNumber (ticker, 'percentage'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -45778,24 +45666,16 @@ module.exports = class bytetrade extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetDepth (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetDepth (params); + return this.parseTickers (response, symbols); } async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetTickers (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetTickers (params); + return this.parseTickers (response, symbols); } parseOHLCV (ohlcv, market = undefined) { @@ -45811,11 +45691,11 @@ module.exports = class bytetrade extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -45845,9 +45725,9 @@ module.exports = class bytetrade extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeInteger (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - const cost = this.safeFloat (trade, 'cost'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + const cost = this.safeNumber (trade, 'cost'); const id = this.safeString (trade, 'id'); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'takerOrMaker'); @@ -45917,12 +45797,12 @@ module.exports = class bytetrade extends Exchange { const timestamp = this.safeInteger (order, 'timestamp'); const datetime = this.safeString (order, 'datetime'); const lastTradeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled'); - const remaining = this.safeFloat (order, 'remaining'); - const cost = this.safeFloat (order, 'cost'); - const average = this.safeFloat (order, 'average'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled'); + const remaining = this.safeNumber (order, 'remaining'); + const cost = this.safeNumber (order, 'cost'); + const average = this.safeNumber (order, 'average'); const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); @@ -46315,7 +46195,7 @@ module.exports = class bytetrade extends Exchange { }; } - async transfer (code, amount, address, message = '', params = {}) { + async transfer (code, amount, fromAccount, toAccount, params = {}) { this.checkRequiredDependencies (); if (this.apiKey === undefined) { throw new ArgumentsRequired ('transfer() requires this.apiKey'); @@ -46333,6 +46213,7 @@ module.exports = class bytetrade extends Exchange { expirationDatetime = expirationDatetime.split ('.')[0]; const feeAmount = '300000000000000'; const defaultDappId = 'Sagittarius'; + const message = this.safeString (params, 'message', ''); const dappId = this.safeString (params, 'dappId', defaultDappId); const eightBytes = this.integerPow ('2', '64'); const byteStringArray = [ @@ -46346,8 +46227,8 @@ module.exports = class bytetrade extends Exchange { this.numberToLE (feeAmount, 8), // string for 32 bit php this.numberToLE (this.apiKey.length, 1), this.stringToBinary (this.encode (this.apiKey)), - this.numberToLE (address.length, 1), - this.stringToBinary (this.encode (address)), + this.numberToLE (toAccount.length, 1), + this.stringToBinary (this.encode (toAccount)), this.numberToLE (assetType, 4), this.numberToLE (this.integerDivide (amountChain, eightBytes), 8), this.numberToLE (this.integerModulo (amountChain, eightBytes), 8), @@ -46368,7 +46249,7 @@ module.exports = class bytetrade extends Exchange { const operation = { 'fee': '300000000000000', 'from': this.apiKey, - 'to': address, + 'to': toAccount, 'asset_type': parseInt (currency['id']), 'amount': amountChain.toString (), 'message': message, @@ -46522,9 +46403,9 @@ module.exports = class bytetrade extends Exchange { const datetime = this.safeString (transaction, 'datetime'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const feeInfo = this.safeValue (transaction, 'fee'); - const feeCost = this.safeFloat (feeInfo, 'cost'); + const feeCost = this.safeNumber (feeInfo, 'cost'); const feeCurrencyId = this.safeString (feeInfo, 'code'); const feeCode = this.safeCurrencyCode (feeCurrencyId, currency); const fee = { @@ -46787,7 +46668,7 @@ module.exports = class bytetrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],58:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],58:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -46822,7 +46703,7 @@ module.exports = class cdax extends huobipro { } }; -},{"./huobipro.js":96}],59:[function(require,module,exports){ +},{"./huobipro.js":94}],59:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -47081,7 +46962,7 @@ module.exports = class cex extends Exchange { 'fee': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimumCurrencyAmount'), + 'min': this.safeNumber (currency, 'minimumCurrencyAmount'), 'max': undefined, }, 'price': { @@ -47093,7 +46974,7 @@ module.exports = class cex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimalWithdrawalAmount'), + 'min': this.safeNumber (currency, 'minimalWithdrawalAmount'), 'max': undefined, }, }, @@ -47176,15 +47057,15 @@ module.exports = class cex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minLotSize'), - 'max': this.safeFloat (market, 'maxLotSize'), + 'min': this.safeNumber (market, 'minLotSize'), + 'max': this.safeNumber (market, 'maxLotSize'), }, 'price': { - 'min': this.safeFloat (market, 'minPrice'), - 'max': this.safeFloat (market, 'maxPrice'), + 'min': this.safeNumber (market, 'minPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { - 'min': this.safeFloat (market, 'minLotSizeS2'), + 'min': this.safeNumber (market, 'minLotSizeS2'), 'max': undefined, }, }, @@ -47205,13 +47086,13 @@ module.exports = class cex extends Exchange { const currencyId = currencyIds[i]; const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); + account['free'] = this.safeString (balance, 'available'); // https://github.com/ccxt/ccxt/issues/5484 - account['used'] = this.safeFloat (balance, 'orders', 0.0); + account['used'] = this.safeString (balance, 'orders', '0'); const code = this.safeCurrencyCode (currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -47240,11 +47121,11 @@ module.exports = class cex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -47286,12 +47167,12 @@ module.exports = class cex extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const volume = this.safeFloat (ticker, 'volume'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'last'); + const volume = this.safeNumber (ticker, 'volume'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'last'); let symbol = undefined; if (market) { symbol = market['symbol']; @@ -47353,8 +47234,8 @@ module.exports = class cex extends Exchange { const id = this.safeString (trade, 'tid'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -47426,8 +47307,8 @@ module.exports = class cex extends Exchange { // "complete": false // } // - const placedAmount = this.safeFloat (response, 'amount'); - const remaining = this.safeFloat (response, 'pending'); + const placedAmount = this.safeNumber (response, 'amount'); + const remaining = this.safeNumber (response, 'pending'); const timestamp = this.safeValue (response, 'time'); const complete = this.safeValue (response, 'complete'); const status = complete ? 'closed' : 'open'; @@ -47446,7 +47327,7 @@ module.exports = class cex extends Exchange { 'side': this.safeString (response, 'type'), 'symbol': symbol, 'status': status, - 'price': this.safeFloat (response, 'price'), + 'price': this.safeNumber (response, 'price'), 'amount': placedAmount, 'cost': undefined, 'average': undefined, @@ -47488,42 +47369,42 @@ module.exports = class cex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - let amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + let amount = this.safeNumber (order, 'amount'); // sell orders can have a negative amount // https://github.com/ccxt/ccxt/issues/5338 if (amount !== undefined) { amount = Math.abs (amount); } - const remaining = this.safeFloat2 (order, 'pending', 'remains'); + const remaining = this.safeNumber2 (order, 'pending', 'remains'); const filled = amount - remaining; let fee = undefined; let cost = undefined; if (market !== undefined) { symbol = market['symbol']; - const taCost = this.safeFloat (order, 'ta:' + market['quote']); - const ttaCost = this.safeFloat (order, 'tta:' + market['quote']); + const taCost = this.safeNumber (order, 'ta:' + market['quote']); + const ttaCost = this.safeNumber (order, 'tta:' + market['quote']); cost = this.sum (taCost, ttaCost); const baseFee = 'fa:' + market['base']; const baseTakerFee = 'tfa:' + market['base']; const quoteFee = 'fa:' + market['quote']; const quoteTakerFee = 'tfa:' + market['quote']; - let feeRate = this.safeFloat (order, 'tradingFeeMaker'); + let feeRate = this.safeNumber (order, 'tradingFeeMaker'); if (!feeRate) { - feeRate = this.safeFloat (order, 'tradingFeeTaker', feeRate); + feeRate = this.safeNumber (order, 'tradingFeeTaker', feeRate); } if (feeRate) { feeRate /= 100.0; // convert to mathematically-correct percentage coefficients: 1.0 = 100% } if ((baseFee in order) || (baseTakerFee in order)) { - const baseFeeCost = this.safeFloat2 (order, baseFee, baseTakerFee); + const baseFeeCost = this.safeNumber2 (order, baseFee, baseTakerFee); fee = { 'currency': market['base'], 'rate': feeRate, 'cost': baseFeeCost, }; } else if ((quoteFee in order) || (quoteTakerFee in order)) { - const quoteFeeCost = this.safeFloat2 (order, quoteFee, quoteTakerFee); + const quoteFeeCost = this.safeNumber2 (order, quoteFee, quoteTakerFee); fee = { 'currency': market['quote'], 'rate': feeRate, @@ -47563,7 +47444,7 @@ module.exports = class cex extends Exchange { // ds: 0 } continue; } - const tradePrice = this.safeFloat (item, 'price'); + const tradePrice = this.safeNumber (item, 'price'); if (tradePrice === undefined) { // this represents the order // { @@ -47667,8 +47548,8 @@ module.exports = class cex extends Exchange { // "fee_amount": "0.03" // } const tradeTimestamp = this.parse8601 (this.safeString (item, 'time')); - const tradeAmount = this.safeFloat (item, 'amount'); - const feeCost = this.safeFloat (item, 'fee_amount'); + const tradeAmount = this.safeNumber (item, 'amount'); + const feeCost = this.safeNumber (item, 'fee_amount'); let absTradeAmount = (tradeAmount < 0) ? -tradeAmount : tradeAmount; let tradeCost = undefined; if (tradeSide === 'sell') { @@ -48013,12 +47894,12 @@ module.exports = class cex extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const side = this.safeString (order, 'type'); - const baseAmount = this.safeFloat (order, 'a:' + baseId + ':cds'); - const quoteAmount = this.safeFloat (order, 'a:' + quoteId + ':cds'); - const fee = this.safeFloat (order, 'f:' + quoteId + ':cds'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const remaining = this.safeFloat (order, 'remains'); + const baseAmount = this.safeNumber (order, 'a:' + baseId + ':cds'); + const quoteAmount = this.safeNumber (order, 'a:' + quoteId + ':cds'); + const fee = this.safeNumber (order, 'f:' + quoteId + ':cds'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const remaining = this.safeNumber (order, 'remains'); const filled = amount - remaining; let orderAmount = undefined; let cost = undefined; @@ -48030,10 +47911,10 @@ module.exports = class cex extends Exchange { cost = quoteAmount; average = orderAmount / cost; } else { - const ta = this.safeFloat (order, 'ta:' + quoteId, 0); - const tta = this.safeFloat (order, 'tta:' + quoteId, 0); - const fa = this.safeFloat (order, 'fa:' + quoteId, 0); - const tfa = this.safeFloat (order, 'tfa:' + quoteId, 0); + const ta = this.safeNumber (order, 'ta:' + quoteId, 0); + const tta = this.safeNumber (order, 'tta:' + quoteId, 0); + const fa = this.safeNumber (order, 'fa:' + quoteId, 0); + const tfa = this.safeNumber (order, 'tfa:' + quoteId, 0); if (side === 'sell') { cost = this.sum (this.sum (ta, tta), this.sum (fa, tfa)); } else { @@ -48172,47 +48053,14 @@ module.exports = class cex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],60:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const foxbit = require ('./foxbit.js'); - -// --------------------------------------------------------------------------- - -module.exports = class chilebit extends foxbit { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'chilebit', - 'name': 'ChileBit', - 'countries': [ 'CL' ], - 'has': { - 'CORS': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg', - 'api': { - 'public': 'https://api.blinktrade.com/api', - 'private': 'https://api.blinktrade.com/tapi', - }, - 'www': 'https://chilebit.net', - 'doc': 'https://blinktrade.com/docs', - }, - 'options': { - 'brokerId': '9', // https://blinktrade.com/docs/#brokers - }, - }); - } -}; - -},{"./foxbit.js":87}],61:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],60:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, RateLimitExceeded, InvalidNonce } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -48620,10 +48468,10 @@ module.exports = class coinbase extends Exchange { const timestamp = this.parse8601 (this.safeValue (transaction, 'created_at')); const updated = this.parse8601 (this.safeValue (transaction, 'updated_at')); const type = this.safeString (transaction, 'resource'); - const amount = this.safeFloat (subtotalObject, 'amount'); + const amount = this.safeNumber (subtotalObject, 'amount'); const currencyId = this.safeString (subtotalObject, 'currency'); const currency = this.safeCurrencyCode (currencyId); - const feeCost = this.safeFloat (feeObject, 'amount'); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -48699,15 +48547,12 @@ module.exports = class coinbase extends Exchange { const orderId = undefined; const side = this.safeString (trade, 'resource'); const type = undefined; - const cost = this.safeFloat (subtotalObject, 'amount'); - const amount = this.safeFloat (amountObject, 'amount'); - let price = undefined; - if (cost !== undefined) { - if ((amount !== undefined) && (amount > 0)) { - price = cost / amount; - } - } - const feeCost = this.safeFloat (feeObject, 'amount'); + const costString = this.safeString (subtotalObject, 'amount'); + const amountString = this.safeString (amountObject, 'amount'); + const cost = this.parseNumber (costString); + const amount = this.parseNumber (amountString); + const price = this.parseNumber (Precise.stringDiv (costString, amountString)); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -48775,7 +48620,7 @@ module.exports = class coinbase extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (quoteCurrency, 'min_size'), + 'min': this.safeNumber (quoteCurrency, 'min_size'), 'max': undefined, }, }, @@ -48857,7 +48702,7 @@ module.exports = class coinbase extends Exchange { 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min_size'), + 'min': this.safeNumber (currency, 'min_size'), 'max': undefined, }, 'price': { @@ -48888,9 +48733,9 @@ module.exports = class coinbase extends Exchange { const buy = await this.publicGetPricesSymbolBuy (request); const sell = await this.publicGetPricesSymbolSell (request); const spot = await this.publicGetPricesSymbolSpot (request); - const ask = this.safeFloat (buy['data'], 'amount'); - const bid = this.safeFloat (sell['data'], 'amount'); - const last = this.safeFloat (spot['data'], 'amount'); + const ask = this.safeNumber (buy['data'], 'amount'); + const bid = this.safeNumber (sell['data'], 'amount'); + const last = this.safeNumber (spot['data'], 'amount'); return { 'symbol': symbol, 'timestamp': timestamp, @@ -48933,7 +48778,7 @@ module.exports = class coinbase extends Exchange { if (this.inArray (balance['type'], accounts)) { const currencyId = this.safeString (balance['balance'], 'currency'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance['balance'], 'amount'); + const total = this.safeNumber (balance['balance'], 'amount'); const free = total; const used = undefined; if (code in result) { @@ -49234,7 +49079,7 @@ module.exports = class coinbase extends Exchange { // } // const amountInfo = this.safeValue (item, 'amount', {}); - let amount = this.safeFloat (amountInfo, 'amount'); + let amount = this.safeNumber (amountInfo, 'amount'); let direction = undefined; if (amount < 0) { direction = 'out'; @@ -49260,7 +49105,7 @@ module.exports = class coinbase extends Exchange { if (feeInfo !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId, currency); - const feeAmount = this.safeFloat (feeInfo, 'amount'); + const feeAmount = this.safeNumber (feeInfo, 'amount'); fee = { 'cost': feeAmount, 'currency': feeCurrencyCode, @@ -49424,7 +49269,7 @@ module.exports = class coinbase extends Exchange { }; -},{"./base/Exchange":6,"./base/errors":8}],62:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],61:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -49457,7 +49302,7 @@ module.exports = class coinbaseprime extends coinbasepro { } }; -},{"./coinbasepro.js":63}],63:[function(require,module,exports){ +},{"./coinbasepro.js":62}],62:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -49465,6 +49310,7 @@ module.exports = class coinbaseprime extends coinbasepro { const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound, OnMaintenance, PermissionDenied, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -49699,7 +49545,7 @@ module.exports = class coinbasepro extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const details = this.safeValue (currency, 'details', {}); - const precision = this.safeFloat (currency, 'max_precision'); + const precision = this.safeNumber (currency, 'max_precision'); const status = this.safeString (currency, 'status'); const active = (status === 'online'); result[code] = { @@ -49713,7 +49559,7 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (details, 'min_size'), + 'min': this.safeNumber (details, 'min_size'), 'max': undefined, }, 'price': { @@ -49725,7 +49571,7 @@ module.exports = class coinbasepro extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (details, 'min_withdrawal_amount'), + 'min': this.safeNumber (details, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -49769,12 +49615,12 @@ module.exports = class coinbasepro extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const priceLimits = { - 'min': this.safeFloat (market, 'quote_increment'), + 'min': this.safeNumber (market, 'quote_increment'), 'max': undefined, }; const precision = { - 'amount': this.safeFloat (market, 'base_increment'), - 'price': this.safeFloat (market, 'quote_increment'), + 'amount': this.safeNumber (market, 'base_increment'), + 'price': this.safeNumber (market, 'quote_increment'), }; const status = this.safeString (market, 'status'); const active = (status === 'online'); @@ -49788,13 +49634,13 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': priceLimits, 'cost': { - 'min': this.safeFloat (market, 'min_market_funds'), - 'max': this.safeFloat (market, 'max_market_funds'), + 'min': this.safeNumber (market, 'min_market_funds'), + 'max': this.safeNumber (market, 'max_market_funds'), }, }, 'active': active, @@ -49851,14 +49697,13 @@ module.exports = class coinbasepro extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'hold'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'hold'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -49915,29 +49760,29 @@ module.exports = class coinbasepro extends Exchange { // } // const timestamp = this.parse8601 (this.safeValue (ticker, 'time')); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'price'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'price'); const symbol = (market === undefined) ? undefined : market['symbol']; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': undefined, 'ask': ask, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -50010,7 +49855,7 @@ module.exports = class coinbasepro extends Exchange { if (market !== undefined) { const feeCurrencyId = this.safeStringLower (market, 'quoteId'); const costField = feeCurrencyId + '_value'; - cost = this.safeFloat (trade, costField); + cost = this.safeNumber (trade, costField); feeCurrency = market['quote']; const liquidity = this.safeString (trade, 'liquidity'); if (liquidity !== undefined) { @@ -50018,7 +49863,7 @@ module.exports = class coinbasepro extends Exchange { feeRate = market[takerOrMaker]; } } - const feeCost = this.safeFloat2 (trade, 'fill_fees', 'fee'); + const feeCost = this.safeNumber2 (trade, 'fill_fees', 'fee'); const fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -50032,10 +49877,12 @@ module.exports = class coinbasepro extends Exchange { if (orderId !== undefined) { side = (trade['side'] === 'buy') ? 'buy' : 'sell'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - cost = amount * price; + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -50097,11 +49944,11 @@ module.exports = class coinbasepro extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -50181,17 +50028,11 @@ module.exports = class coinbasepro extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'filled_size'); - const amount = this.safeFloat (order, 'size', filled); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'executed_value'); - const feeCost = this.safeFloat (order, 'fill_fees'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'filled_size'); + const amount = this.safeNumber (order, 'size', filled); + const cost = this.safeNumber (order, 'executed_value'); + const feeCost = this.safeNumber (order, 'fill_fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -50209,9 +50050,9 @@ module.exports = class coinbasepro extends Exchange { const side = this.safeString (order, 'side'); const timeInForce = this.safeString (order, 'time_in_force'); const postOnly = this.safeValue (order, 'post_only'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -50229,11 +50070,11 @@ module.exports = class coinbasepro extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -50323,7 +50164,7 @@ module.exports = class coinbasepro extends Exchange { request['client_oid'] = clientOrderId; params = this.omit (params, [ 'clientOrderId', 'client_oid' ]); } - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop_price'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stop_price'); if (stopPrice !== undefined) { request['stop_price'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, [ 'stopPrice', 'stop_price' ]); @@ -50337,7 +50178,7 @@ module.exports = class coinbasepro extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['size'] = this.amountToPrecision (symbol, amount); } else if (type === 'market') { - let cost = this.safeFloat2 (params, 'cost', 'funds'); + let cost = this.safeNumber2 (params, 'cost', 'funds'); if (cost === undefined) { if (price !== undefined) { cost = amount * price; @@ -50408,19 +50249,6 @@ module.exports = class coinbasepro extends Exchange { return await this.privateDeleteOrders (this.extend (request, params)); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - const cost = amount * price; - const currency = market['quote']; - return { - 'type': takerOrMaker, - 'currency': currency, - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (currency, rate * cost)), - }; - } - async fetchPaymentMethods (params = {}) { return await this.privateGetPaymentMethods (params); } @@ -50559,7 +50387,7 @@ module.exports = class coinbasepro extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (transaction); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let type = this.safeString (transaction, 'type'); let address = this.safeString (details, 'crypto_address'); const tag = this.safeString (details, 'destination_tag'); @@ -50568,7 +50396,7 @@ module.exports = class coinbasepro extends Exchange { if (type === 'withdraw') { type = 'withdrawal'; address = this.safeString (details, 'sent_to_address', address); - const feeCost = this.safeFloat (details, 'fee'); + const feeCost = this.safeNumber (details, 'fee'); if (feeCost !== undefined) { if (amount !== undefined) { amount -= feeCost; @@ -50682,13 +50510,14 @@ module.exports = class coinbasepro extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],64:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],63:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -50812,12 +50641,12 @@ module.exports = class coincheck extends Exchange { if (currencyId in balances) { const account = this.account (); const reserved = currencyId + '_reserved'; - account['free'] = this.safeFloat (balances, currencyId); - account['used'] = this.safeFloat (balances, reserved); + account['free'] = this.safeString (balances, currencyId); + account['used'] = this.safeString (balances, reserved); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -50855,23 +50684,13 @@ module.exports = class coincheck extends Exchange { const id = this.safeString (order, 'id'); const side = this.safeString (order, 'order_type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const amount = this.safeFloat (order, 'pending_amount'); - const remaining = this.safeFloat (order, 'pending_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = Math.max (amount - remaining, 0); - if (price !== undefined) { - cost = filled * price; - } - } - } + const amount = this.safeNumber (order, 'pending_amount'); + const remaining = this.safeNumber (order, 'pending_amount'); + const price = this.safeNumber (order, 'rate'); const status = undefined; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -50879,7 +50698,7 @@ module.exports = class coincheck extends Exchange { 'lastTradeTimestamp': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'side': side, 'type': undefined, 'timeInForce': undefined, @@ -50888,12 +50707,12 @@ module.exports = class coincheck extends Exchange { 'symbol': symbol, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'info': order, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -50917,16 +50736,16 @@ module.exports = class coincheck extends Exchange { }; const ticker = await this.publicGetTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -50936,7 +50755,7 @@ module.exports = class coincheck extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -50945,7 +50764,7 @@ module.exports = class coincheck extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'rate'); + const priceString = this.safeString (trade, 'rate'); const marketId = this.safeString (trade, 'pair'); market = this.safeValue (this.markets_by_id, marketId, market); let symbol = undefined; @@ -50972,7 +50791,7 @@ module.exports = class coincheck extends Exchange { } } let takerOrMaker = undefined; - let amount = undefined; + let amountString = undefined; let cost = undefined; let side = undefined; let fee = undefined; @@ -50984,24 +50803,22 @@ module.exports = class coincheck extends Exchange { takerOrMaker = 'maker'; } const funds = this.safeValue (trade, 'funds', {}); - amount = this.safeFloat (funds, baseId); - cost = this.safeFloat (funds, quoteId); + amountString = this.safeString (funds, baseId); + cost = this.safeNumber (funds, quoteId); fee = { 'currency': this.safeString (trade, 'fee_currency'), - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), }; side = this.safeString (trade, 'side'); orderId = this.safeString (trade, 'order_id'); } else { - amount = this.safeFloat (trade, 'amount'); + amountString = this.safeString (trade, 'amount'); side = this.safeString (trade, 'order_type'); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -51072,6 +50889,10 @@ module.exports = class coincheck extends Exchange { return await this.privateDeleteExchangeOrdersId (this.extend (request, params)); } + nonce () { + return this.milliseconds (); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { let url = this.urls['api'] + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); @@ -51118,13 +50939,14 @@ module.exports = class coincheck extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],65:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],64:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -51335,8 +51157,8 @@ module.exports = class coinegg extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; let change = undefined; let average = undefined; @@ -51350,11 +51172,11 @@ module.exports = class coinegg extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -51364,8 +51186,8 @@ module.exports = class coinegg extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVol'), 'info': ticker, }; } @@ -51394,15 +51216,12 @@ module.exports = class coinegg extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const type = 'limit'; const side = this.safeString (trade, 'type'); const id = this.safeString (trade, 'tid'); @@ -51449,9 +51268,9 @@ module.exports = class coinegg extends Exchange { result[code] = this.account (); } const type = (accountType === 'lock') ? 'used' : 'free'; - result[code][type] = this.safeFloat (balances, key); + result[code][type] = this.safeString (balances, key); } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -51460,15 +51279,9 @@ module.exports = class coinegg extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let status = this.safeString (order, 'status'); if (status === 'cancelled') { status = 'canceled'; @@ -51479,7 +51292,7 @@ module.exports = class coinegg extends Exchange { const type = 'limit'; const side = this.safeString (order, 'type'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -51495,13 +51308,13 @@ module.exports = class coinegg extends Exchange { 'stopPrice': undefined, 'cost': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'trades': undefined, 'fee': undefined, 'info': info, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -51637,13 +51450,14 @@ module.exports = class coinegg extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],66:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],65:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, OrderNotFound, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -51836,13 +51650,13 @@ module.exports = class coinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': this.safeFloat (market, 'taker_fee_rate'), - 'maker': this.safeFloat (market, 'maker_fee_rate'), + 'taker': this.safeNumber (market, 'taker_fee_rate'), + 'maker': this.safeNumber (market, 'maker_fee_rate'), 'info': market, 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -51862,16 +51676,16 @@ module.exports = class coinex extends Exchange { symbol = market['symbol']; } ticker = this.safeValue (ticker, 'ticker', {}); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -51881,7 +51695,7 @@ module.exports = class coinex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat2 (ticker, 'vol', 'volume'), + 'baseVolume': this.safeNumber2 (ticker, 'vol', 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -51941,16 +51755,18 @@ module.exports = class coinex extends Exchange { } const tradeId = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market); - let cost = this.safeFloat (trade, 'deal_money'); - if (!cost) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); + let cost = this.safeNumber (trade, 'deal_money'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_asset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -52003,11 +51819,11 @@ module.exports = class coinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -52068,11 +51884,11 @@ module.exports = class coinex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -52111,11 +51927,11 @@ module.exports = class coinex extends Exchange { // } // const timestamp = this.safeTimestamp (order, 'create_time'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'deal_money'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'deal_amount'); - const average = this.safeFloat (order, 'avg_price'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'deal_money'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'deal_amount'); + const average = this.safeNumber (order, 'avg_price'); let symbol = undefined; const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); @@ -52127,11 +51943,11 @@ module.exports = class coinex extends Exchange { feeCurrency = market['quote']; } } - const remaining = this.safeFloat (order, 'left'); + const remaining = this.safeNumber (order, 'left'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -52153,10 +51969,10 @@ module.exports = class coinex extends Exchange { 'trades': undefined, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'deal_fee'), + 'cost': this.safeNumber (order, 'deal_fee'), }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -52402,8 +52218,8 @@ module.exports = class coinex extends Exchange { const timestamp = this.safeTimestamp (transaction, 'create_time'); const type = ('coin_withdraw_id' in transaction) ? 'withdraw' : 'deposit'; const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'tx_fee'); + let amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'tx_fee'); if (type === 'deposit') { feeCost = 0; } @@ -52594,13 +52410,14 @@ module.exports = class coinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],67:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],66:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, RateLimitExceeded, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -52733,11 +52550,11 @@ module.exports = class coinfalcon extends Exchange { 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'change_in_24h'), + 'change': this.safeNumber (ticker, 'change_in_24h'), 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -52774,20 +52591,17 @@ module.exports = class coinfalcon extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } const tradeId = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'order_id'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = this.safeString (trade, 'fee_currency_code'); fee = { @@ -52855,14 +52669,13 @@ module.exports = class coinfalcon extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available_balance'), - 'used': this.safeFloat (balance, 'hold_balance'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'hold_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -52897,19 +52710,9 @@ module.exports = class coinfalcon extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'size_filled'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (price !== undefined) { - cost = filled * price; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'size_filled'); const status = this.parseOrderStatus (this.safeString (order, 'status')); let type = this.safeString (order, 'operation_type'); if (type !== undefined) { @@ -52918,7 +52721,7 @@ module.exports = class coinfalcon extends Exchange { } const side = this.safeString (order, 'order_type'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -52931,16 +52734,16 @@ module.exports = class coinfalcon extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'lastTradeTimestamp': undefined, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -53050,13 +52853,14 @@ module.exports = class coinfalcon extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],68:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],67:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ExchangeError, InvalidNonce, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -53158,14 +52962,14 @@ module.exports = class coinfloor extends Exchange { const baseIdLower = this.safeStringLower (market, 'baseId'); const quoteIdLower = this.safeStringLower (market, 'quoteId'); result[base] = { - 'free': this.safeFloat (response, baseIdLower + '_available'), - 'used': this.safeFloat (response, baseIdLower + '_reserved'), - 'total': this.safeFloat (response, baseIdLower + '_balance'), + 'free': this.safeNumber (response, baseIdLower + '_available'), + 'used': this.safeNumber (response, baseIdLower + '_reserved'), + 'total': this.safeNumber (response, baseIdLower + '_balance'), }; result[quote] = { - 'free': this.safeFloat (response, quoteIdLower + '_available'), - 'used': this.safeFloat (response, quoteIdLower + '_reserved'), - 'total': this.safeFloat (response, quoteIdLower + '_balance'), + 'free': this.safeNumber (response, quoteIdLower + '_available'), + 'used': this.safeNumber (response, quoteIdLower + '_reserved'), + 'total': this.safeNumber (response, quoteIdLower + '_balance'), }; return this.parseBalance (result); } @@ -53186,22 +52990,22 @@ module.exports = class coinfloor extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -53230,14 +53034,11 @@ module.exports = class coinfloor extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -53355,8 +53156,8 @@ module.exports = class coinfloor extends Exchange { const parts = key.split ('_'); const numParts = parts.length; if (numParts === 2) { - const tmpBaseAmount = this.safeFloat (item, parts[0]); - const tmpQuoteAmount = this.safeFloat (item, parts[1]); + const tmpBaseAmount = this.safeNumber (item, parts[0]); + const tmpQuoteAmount = this.safeNumber (item, parts[1]); if (tmpBaseAmount !== undefined && tmpQuoteAmount !== undefined) { baseId = parts[0]; quoteId = parts[1]; @@ -53372,7 +53173,7 @@ module.exports = class coinfloor extends Exchange { const referenceId = this.safeString (item, 'id'); const timestamp = this.parse8601 (this.safeString (item, 'datetime')); let fee = undefined; - const feeCost = this.safeFloat (item, 'fee'); + const feeCost = this.safeNumber (item, 'fee'); const result = { 'id': undefined, 'timestamp': timestamp, @@ -53476,8 +53277,8 @@ module.exports = class coinfloor extends Exchange { 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, 'type': type, - 'price': this.safeFloat (response, 'price'), - 'remaining': this.safeFloat (response, 'amount'), + 'price': this.safeNumber (response, 'price'), + 'remaining': this.safeNumber (response, 'amount'), 'info': response, }; } @@ -53502,19 +53303,14 @@ module.exports = class coinfloor extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let side = undefined; const status = this.safeString (order, 'status'); - if (order['type'] === 0) { + const rawType = this.safeString (order, 'type'); + if (rawType === '0') { side = 'buy'; - } else if (order['type'] === 1) { + } else if (rawType === '1') { side = 'sell'; } let symbol = undefined; @@ -53522,7 +53318,7 @@ module.exports = class coinfloor extends Exchange { symbol = market['symbol']; } const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -53540,11 +53336,11 @@ module.exports = class coinfloor extends Exchange { 'amount': undefined, 'filled': undefined, 'remaining': amount, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -53603,13 +53399,14 @@ module.exports = class coinfloor extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],69:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],68:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -53771,14 +53568,14 @@ module.exports = class coingi extends Exchange { const currencyId = this.safeString (balance['currency'], 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - const blocked = this.safeFloat (balance, 'blocked'); - const inOrders = this.safeFloat (balance, 'inOrders'); - const withdrawing = this.safeFloat (balance, 'withdrawing'); - account['used'] = this.sum (blocked, inOrders, withdrawing); + account['free'] = this.safeString (balance, 'available'); + const blocked = this.safeString (balance, 'blocked'); + const inOrders = this.safeString (balance, 'inOrders'); + const withdrawing = this.safeString (balance, 'withdrawing'); + account['used'] = Precise.stringAdd (Precise.stringAdd (blocked, inOrders), withdrawing); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = 512, params = {}) { @@ -53804,11 +53601,11 @@ module.exports = class coingi extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -53818,8 +53615,8 @@ module.exports = class coingi extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'counterVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'counterVolume'), 'info': ticker, }; } @@ -53852,14 +53649,11 @@ module.exports = class coingi extends Exchange { } parseTrade (trade, market = undefined) { - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const id = this.safeString (trade, 'id'); const marketId = this.safeString (trade, 'currencyPair'); @@ -53953,7 +53747,7 @@ module.exports = class coingi extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],70:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],69:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -54164,16 +53958,16 @@ module.exports = class coinmarketcap extends Exchange { if (timestamp === undefined) { timestamp = this.milliseconds (); } - const change = this.safeFloat (ticker, 'percent_change_24h'); + const change = this.safeNumber (ticker, 'percent_change_24h'); let last = undefined; let symbol = undefined; let volume = undefined; if (market !== undefined) { symbol = market['symbol']; const priceKey = 'price_' + market['quoteId']; - last = this.safeFloat (ticker, priceKey); + last = this.safeNumber (ticker, priceKey); const volumeKey = '24h_volume_' + market['quoteId']; - volume = this.safeFloat (ticker, volumeKey); + volume = this.safeNumber (ticker, volumeKey); } return { 'symbol': symbol, @@ -54302,13 +54096,14 @@ module.exports = class coinmarketcap extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],71:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],70:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder, OrderNotFound, RateLimitExceeded, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -54535,7 +54330,7 @@ module.exports = class coinmate extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -54563,12 +54358,12 @@ module.exports = class coinmate extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -54591,16 +54386,16 @@ module.exports = class coinmate extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'data'); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'vwap': undefined, 'askVolume': undefined, 'open': undefined, @@ -54610,7 +54405,7 @@ module.exports = class coinmate extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'amount'), + 'baseVolume': this.safeNumber (ticker, 'amount'), 'quoteVolume': undefined, 'info': ticker, }; @@ -54679,8 +54474,8 @@ module.exports = class coinmate extends Exchange { // } // const timestamp = this.safeInteger (item, 'timestamp'); - const amount = this.safeFloat (item, 'amount'); - const fee = this.safeFloat (item, 'fee'); + const amount = this.safeNumber (item, 'amount'); + const fee = this.safeNumber (item, 'fee'); const txid = this.safeString (item, 'txid'); const address = this.safeString (item, 'destination'); const tag = this.safeString (item, 'destinationTag'); @@ -54758,21 +54553,18 @@ module.exports = class coinmate extends Exchange { // const marketId = this.safeString (trade, 'currencyPair'); market = this.safeMarket (marketId, market, '_'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeStringLower2 (trade, 'type', 'tradeType'); const type = this.safeStringLower (trade, 'orderType'); const orderId = this.safeString (trade, 'orderId'); const id = this.safeString (trade, 'transactionId'); const timestamp = this.safeInteger2 (trade, 'timestamp', 'createdTimestamp'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -54913,11 +54705,11 @@ module.exports = class coinmate extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.safeInteger (order, 'timestamp'); const side = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'originalAmount'); - let remaining = this.safeFloat (order, 'remainingAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'originalAmount'); + let remaining = this.safeNumber (order, 'remainingAmount'); if (remaining === undefined) { - remaining = this.safeFloat (order, 'amount'); + remaining = this.safeNumber (order, 'amount'); } let status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.parseOrderType (this.safeString (order, 'orderTradeType')); @@ -54932,11 +54724,11 @@ module.exports = class coinmate extends Exchange { cost = filled * price; } } - const average = this.safeFloat (order, 'avgPrice'); + const average = this.safeNumber (order, 'avgPrice'); const marketId = this.safeString (order, 'currencyPair'); const symbol = this.safeSymbol (marketId, market, '_'); const clientOrderId = this.safeString (order, 'clientOrderId'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); return { 'id': id, 'clientOrderId': clientOrderId, @@ -55064,13 +54856,14 @@ module.exports = class coinmate extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],72:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],71:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, BadRequest, ExchangeError, ArgumentsRequired, OrderNotFound, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -55209,11 +55002,11 @@ module.exports = class coinone extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'avail'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -55266,13 +55059,13 @@ module.exports = class coinone extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const first = this.safeFloat (ticker, 'first'); - const last = this.safeFloat (ticker, 'last'); + const first = this.safeNumber (ticker, 'first'); + const last = this.safeNumber (ticker, 'last'); let average = undefined; if (first !== undefined && last !== undefined) { average = this.sum (first, last) / 2; } - const previousClose = this.safeFloat (ticker, 'yesterday_last'); + const previousClose = this.safeNumber (ticker, 'yesterday_last'); let change = undefined; let percentage = undefined; if (last !== undefined && previousClose !== undefined) { @@ -55286,8 +55079,8 @@ module.exports = class coinone extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -55300,7 +55093,7 @@ module.exports = class coinone extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -55346,20 +55139,17 @@ module.exports = class coinone extends Exchange { side = 'buy'; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'fee'); + let feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); - let feeRate = this.safeFloat (trade, 'feeRate'); + let feeRate = this.safeNumber (trade, 'feeRate'); feeRate = Math.abs (feeRate); let feeCurrencyCode = undefined; if (market !== undefined) { @@ -55519,7 +55309,7 @@ module.exports = class coinone extends Exchange { // } // const id = this.safeString (order, 'orderId'); - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); const timestamp = this.safeTimestamp (order, 'timestamp'); let side = this.safeString (order, 'type'); if (side === 'ask') { @@ -55527,9 +55317,8 @@ module.exports = class coinone extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const remaining = this.safeFloat (order, 'remainQty'); - let filled = undefined; - const amount = this.safeFloat (order, 'qty'); + const remaining = this.safeNumber (order, 'remainQty'); + const amount = this.safeNumber (order, 'qty'); let status = this.safeString (order, 'status'); // https://github.com/ccxt/ccxt/pull/7067 if (status === 'live') { @@ -55539,14 +55328,7 @@ module.exports = class coinone extends Exchange { } } } - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (amount - remaining); - } status = this.parseOrderStatus (status); - let cost = undefined; - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } let symbol = undefined; let base = undefined; let quote = undefined; @@ -55566,16 +55348,16 @@ module.exports = class coinone extends Exchange { quote = market['quote']; } let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = (side === 'sell') ? quote : base; fee = { 'cost': feeCost, - 'rate': this.safeFloat (order, 'feeRate'), + 'rate': this.safeNumber (order, 'feeRate'), 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -55589,15 +55371,15 @@ module.exports = class coinone extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': amount, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -55672,8 +55454,8 @@ module.exports = class coinone extends Exchange { // eslint-disable-next-line quotes throw new ArgumentsRequired (this.id + " cancelOrder() requires a symbol argument. To cancel the order, pass a symbol argument and {'price': 12345, 'qty': 1.2345, 'is_ask': 0} in the params argument of cancelOrder."); } - const price = this.safeFloat (params, 'price'); - const qty = this.safeFloat (params, 'qty'); + const price = this.safeNumber (params, 'price'); + const qty = this.safeNumber (params, 'qty'); const isAsk = this.safeInteger (params, 'is_ask'); if ((price === undefined) || (qty === undefined) || (isAsk === undefined)) { // eslint-disable-next-line quotes @@ -55748,13 +55530,14 @@ module.exports = class coinone extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],73:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],72:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -55874,7 +55657,7 @@ module.exports = class coinspot extends Exchange { const balance = currencies[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } } @@ -55884,11 +55667,11 @@ module.exports = class coinspot extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -55908,16 +55691,16 @@ module.exports = class coinspot extends Exchange { id = id.toLowerCase (); const ticker = response['prices'][id]; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -55965,11 +55748,13 @@ module.exports = class coinspot extends Exchange { // "market":"BTC/AUD" // } // - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'total'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger (trade, 'solddate'); const marketId = this.safeString (trade, 'market'); @@ -56037,13 +55822,15 @@ module.exports = class coinspot extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],74:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],73:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, InvalidNonce, RequestTimeout, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, AuthenticationError, BadSymbol } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -56150,6 +55937,7 @@ module.exports = class crex24 extends Exchange { ], }, }, + 'precisionMode': TICK_SIZE, 'fees': { 'trading': { 'tierBased': true, @@ -56170,6 +55958,7 @@ module.exports = class crex24 extends Exchange { 'BIT': 'BitMoney', 'BULL': 'BuySell', 'CREDIT': 'TerraCredit', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'GHOST': 'GHOSTPRISM', 'IQ': 'IQ.Cash', 'PUT': 'PutinCoin', @@ -56203,6 +55992,7 @@ module.exports = class crex24 extends Exchange { 'API Key': AuthenticationError, // "API Key '9edc48de-d5b0-4248-8e7e-f59ffcd1c7f1' doesn't exist." 'Insufficient funds': InsufficientFunds, // "Insufficient funds: new order requires 10 ETH which is more than the available balance." 'has been delisted.': BadSymbol, // {"errorDescription":"Instrument '$PAC-BTC' has been delisted."} + 'is currently suspended.': BadSymbol, // {"errorDescription":"Trading in BITG-BTC is currently suspended."} 'Mandatory parameter': BadRequest, // {"errorDescription":"Mandatory parameter 'feeCurrency' is missing."} }, }, @@ -56244,12 +56034,12 @@ module.exports = class crex24 extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const tickSize = this.safeValue (market, 'tickSize'); - const minPrice = this.safeValue (market, 'minPrice'); - const minAmount = this.safeFloat (market, 'minVolume'); + const tickSize = this.safeNumber (market, 'tickSize'); + const minPrice = this.safeNumber (market, 'minPrice'); + const minAmount = this.safeNumber (market, 'minVolume'); const precision = { - 'amount': this.precisionFromString (this.numberToString (minAmount)), - 'price': this.precisionFromString (this.numberToString (tickSize)), + 'amount': minAmount, + 'price': tickSize, }; const active = (market['state'] === 'active'); result.push ({ @@ -56314,7 +56104,8 @@ module.exports = class crex24 extends Exchange { const currency = response[i]; const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); - const precision = this.safeInteger (currency, 'withdrawalPrecision'); + const withdrawalPrecision = this.safeInteger (currency, 'withdrawalPrecision'); + const precision = Math.pow (10, -withdrawalPrecision); const address = this.safeValue (currency, 'BaseAddress'); const active = (currency['depositsAllowed'] && currency['withdrawalsAllowed'] && !currency['isDelisted']); const type = currency['isFiat'] ? 'fiat' : 'crypto'; @@ -56326,7 +56117,7 @@ module.exports = class crex24 extends Exchange { 'type': type, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'flatWithdrawalFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'flatWithdrawalFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -56342,12 +56133,12 @@ module.exports = class crex24 extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -56377,11 +56168,11 @@ module.exports = class crex24 extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -56433,16 +56224,16 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); const marketId = this.safeString (ticker, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -56450,10 +56241,10 @@ module.exports = class crex24 extends Exchange { 'last': last, 'previousClose': undefined, // previous day close 'change': undefined, - 'percentage': this.safeFloat (ticker, 'percentChange'), + 'percentage': this.safeNumber (ticker, 'percentChange'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -56523,14 +56314,6 @@ module.exports = class crex24 extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - parseTrade (trade, market = undefined) { // // public fetchTrades @@ -56555,14 +56338,11 @@ module.exports = class crex24 extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'orderId'); @@ -56571,7 +56351,7 @@ module.exports = class crex24 extends Exchange { let fee = undefined; const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCode = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -56632,11 +56412,11 @@ module.exports = class crex24 extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -56705,50 +56485,19 @@ module.exports = class crex24 extends Exchange { const marketId = this.safeString (order, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remainingVolume'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remainingVolume'); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'lastUpdate')); - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = amount - remaining; - if (this.options['parseOrderToPrecision']) { - filled = parseFloat (this.amountToPrecision (symbol, filled)); - } - filled = Math.max (filled, 0.0); - if (price !== undefined) { - cost = price * filled; - } - } - } const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeString (order, 'side'); const fee = undefined; const trades = undefined; - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const average = undefined; const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -56762,14 +56511,14 @@ module.exports = class crex24 extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -56804,7 +56553,7 @@ module.exports = class crex24 extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -57223,8 +56972,8 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'createdAt')); const updated = this.parse8601 (this.safeString (transaction, 'processedAt')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); const fee = { 'cost': feeCost, 'currency': code, @@ -57349,14 +57098,15 @@ module.exports = class crex24 extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],75:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],74:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -57444,6 +57194,7 @@ module.exports = class currencycom extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.002, @@ -57602,7 +57353,7 @@ module.exports = class currencycom extends Exchange { const filtersByType = this.indexBy (filters, 'filterType'); const precision = { 'amount': 1 / Math.pow (1, this.safeInteger (market, 'baseAssetPrecision')), - 'price': this.safeFloat (market, 'tickSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'TRADING'); @@ -57635,14 +57386,14 @@ module.exports = class currencycom extends Exchange { 'max': undefined, }, 'cost': { - 'min': -1 * Math.log10 (precision['amount']), + 'min': -Math.log10 (precision['amount']), 'max': undefined, }, }, }; - const exchangeFee = this.safeFloat2 (market, 'exchangeFee', 'tradingFee'); - const makerFee = this.safeFloat (market, 'makerFee', exchangeFee); - const takerFee = this.safeFloat (market, 'takerFee', exchangeFee); + const exchangeFee = this.safeNumber2 (market, 'exchangeFee', 'tradingFee'); + const makerFee = this.safeNumber (market, 'makerFee', exchangeFee); + const takerFee = this.safeNumber (market, 'takerFee', exchangeFee); if (makerFee !== undefined) { entry['maker'] = makerFee / 100; } @@ -57651,65 +57402,44 @@ module.exports = class currencycom extends Exchange { } if ('PRICE_FILTER' in filtersByType) { const filter = this.safeValue (filtersByType, 'PRICE_FILTER', {}); - entry['precision']['price'] = this.safeFloat (filter, 'tickSize'); + entry['precision']['price'] = this.safeNumber (filter, 'tickSize'); // PRICE_FILTER reports zero values for maxPrice // since they updated filter types in November 2018 // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } } if ('LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'LOT_SIZE', {}); - entry['precision']['amount'] = this.safeFloat (filter, 'stepSize'); + entry['precision']['amount'] = this.safeNumber (filter, 'stepSize'); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat (filter, 'minNotional'); + entry['limits']['cost']['min'] = this.safeNumber (filter, 'minNotional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { const response = await this.privateGetAccount (params); // @@ -57756,8 +57486,8 @@ module.exports = class currencycom extends Exchange { const response = await this.privateGetAccount (params); return { 'info': response, - 'maker': this.safeFloat (response, 'makerCommission'), - 'taker': this.safeFloat (response, 'takerCommission'), + 'maker': this.safeNumber (response, 'makerCommission'), + 'taker': this.safeNumber (response, 'takerCommission'), }; } @@ -57791,11 +57521,11 @@ module.exports = class currencycom extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -57894,8 +57624,8 @@ module.exports = class currencycom extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); - const open = this.safeFloat (ticker, 'openPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); let average = undefined; if ((open !== undefined) && (last !== undefined)) { average = this.sum (open, last) / 2; @@ -57904,22 +57634,22 @@ module.exports = class currencycom extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), 'open': open, 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -57954,14 +57684,6 @@ module.exports = class currencycom extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24hr (params); @@ -57994,11 +57716,11 @@ module.exports = class currencycom extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -58064,8 +57786,11 @@ module.exports = class currencycom extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -58081,7 +57806,7 @@ module.exports = class currencycom extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -58103,7 +57828,7 @@ module.exports = class currencycom extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': fee, }; } @@ -58179,66 +57904,21 @@ module.exports = class currencycom extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); + const remaining = undefined; + const cost = this.safeNumber (order, 'cummulativeQuoteQty'); const id = this.safeString (order, 'orderId'); const type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeStringLower (order, 'side'); - let fee = undefined; let trades = undefined; const fills = this.safeValue (order, 'fills'); if (fills !== undefined) { trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'timestamp': timestamp, @@ -58252,13 +57932,13 @@ module.exports = class currencycom extends Exchange { 'stopPrice': undefined, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -58470,7 +58150,7 @@ module.exports = class currencycom extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],76:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],75:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -58478,6 +58158,7 @@ module.exports = class currencycom extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, BadRequest, BadSymbol, InvalidOrder, AuthenticationError, ArgumentsRequired, OrderNotFound, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -58731,14 +58412,14 @@ module.exports = class delta extends Exchange { 'name': this.safeString (currency, 'name'), 'info': currency, // the original payload 'active': active, - 'fee': this.safeFloat (currency, 'base_withdrawal_fee'), + 'fee': this.safeNumber (currency, 'base_withdrawal_fee'), 'precision': 1 / Math.pow (10, precision), 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal_amount'), + 'min': this.safeNumber (currency, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -58872,26 +58553,26 @@ module.exports = class delta extends Exchange { } const precision = { 'amount': 1.0, // number of contracts - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; const limits = { 'amount': { 'min': 1.0, - 'max': this.safeFloat (market, 'position_size_limit'), + 'max': this.safeNumber (market, 'position_size_limit'), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; const state = this.safeString (market, 'state'); const active = (state === 'live'); - const maker = this.safeFloat (market, 'maker_commission_rate'); - const taker = this.safeFloat (market, 'taker_commission_rate'); + const maker = this.safeNumber (market, 'maker_commission_rate'); + const taker = this.safeNumber (market, 'taker_commission_rate'); result.push ({ 'id': id, 'numericId': numericId, @@ -58939,8 +58620,8 @@ module.exports = class delta extends Exchange { const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.001); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; let percentage = undefined; @@ -58951,15 +58632,15 @@ module.exports = class delta extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'turnover'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'turnover'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -59129,12 +58810,11 @@ module.exports = class delta extends Exchange { const orderId = this.safeString (trade, 'order_id'); let timestamp = this.parse8601 (this.safeString (trade, 'created_at')); timestamp = this.safeIntegerProduct (trade, 'timestamp', 0.001, timestamp); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const product = this.safeValue (trade, 'product', {}); const marketId = this.safeString (product, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -59153,7 +58833,7 @@ module.exports = class delta extends Exchange { if (type !== undefined) { type = type.replace ('_order', ''); } - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { const settlingAsset = this.safeValue (product, 'settling_asset', {}); @@ -59220,11 +58900,11 @@ module.exports = class delta extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -59294,11 +58974,11 @@ module.exports = class delta extends Exchange { const currency = this.safeValue (currenciesByNumericId, currencyId); const code = (currency === undefined) ? currencyId : currency['code']; const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchPosition (symbol, params = undefined) { @@ -59322,7 +59002,7 @@ module.exports = class delta extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPositionsMargined (params); // @@ -59403,20 +59083,12 @@ module.exports = class delta extends Exchange { const side = this.safeString (order, 'side'); let type = this.safeString (order, 'order_type'); type = type.replace ('_order', ''); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'unfilled_size'); - let filled = undefined; - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let cost = undefined; - const average = this.safeFloat (order, 'average_fill_price'); - if ((average !== undefined) && filled) { - cost = average * filled; - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'unfilled_size'); + const average = this.safeNumber (order, 'average_fill_price'); let fee = undefined; - const feeCost = this.safeFloat (order, 'paid_commission'); + const feeCost = this.safeNumber (order, 'paid_commission'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -59429,7 +59101,7 @@ module.exports = class delta extends Exchange { 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -59441,14 +59113,14 @@ module.exports = class delta extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -59847,9 +59519,9 @@ module.exports = class delta extends Exchange { const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId'); currency = this.safeValue (currenciesByNumericId, currencyId, currency); const code = (currency === undefined) ? undefined : currency['code']; - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'created_at')); - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const before = Math.max (0, after - amount); const status = 'ok'; return { @@ -59955,7 +59627,7 @@ module.exports = class delta extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],77:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],76:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -59963,6 +59635,7 @@ module.exports = class delta extends Exchange { const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, DDoSProtection, NotSupported, ExchangeNotAvailable, InsufficientFunds, BadRequest, InvalidAddress, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -60393,8 +60066,8 @@ module.exports = class deribit extends Exchange { const future = (type === 'future'); const option = (type === 'option'); const active = this.safeValue (market, 'is_active'); - const minTradeAmount = this.safeFloat (market, 'min_trade_amount'); - const tickSize = this.safeFloat (market, 'tick_size'); + const minTradeAmount = this.safeNumber (market, 'min_trade_amount'); + const tickSize = this.safeNumber (market, 'tick_size'); const precision = { 'amount': minTradeAmount, 'price': tickSize, @@ -60406,8 +60079,8 @@ module.exports = class deribit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_commission'), - 'maker': this.safeFloat (market, 'maker_commission'), + 'taker': this.safeNumber (market, 'taker_commission'), + 'maker': this.safeNumber (market, 'maker_commission'), 'limits': { 'amount': { 'min': minTradeAmount, @@ -60490,11 +60163,11 @@ module.exports = class deribit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const currencyCode = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableFunds'); - account['used'] = this.safeFloat (balance, 'maintenanceMargin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'maintenanceMargin'); + account['total'] = this.safeString (balance, 'equity'); result[currencyCode] = account; - return this.parseBalance (result); + return this.parseBalance (result, false); } async createDepositAddress (code, params = {}) { @@ -60612,18 +60285,18 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger2 (ticker, 'timestamp', 'creation_timestamp'); const marketId = this.safeString (ticker, 'instrument_name'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat2 (ticker, 'last_price', 'last'); + const last = this.safeNumber2 (ticker, 'last_price', 'last'); const stats = this.safeValue (ticker, 'stats', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (stats, 'high', 'max_price'), - 'low': this.safeFloat2 (stats, 'low', 'min_price'), - 'bid': this.safeFloat2 (ticker, 'best_bid_price', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_amount'), - 'ask': this.safeFloat2 (ticker, 'best_ask_price', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_amount'), + 'high': this.safeNumber2 (stats, 'high', 'max_price'), + 'low': this.safeNumber2 (stats, 'low', 'min_price'), + 'bid': this.safeNumber2 (ticker, 'best_bid_price', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_amount'), + 'ask': this.safeNumber2 (ticker, 'best_ask_price', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_amount'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -60633,7 +60306,7 @@ module.exports = class deribit extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (stats, 'volume'), + 'quoteVolume': this.safeNumber (stats, 'volume'), 'info': ticker, }; } @@ -60820,21 +60493,18 @@ module.exports = class deribit extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const liquidity = this.safeString (trade, 'liquidity'); let takerOrMaker = undefined; if (liquidity !== undefined) { // M = maker, T = taker, MT = both takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -61014,31 +60684,21 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger (order, 'creation_timestamp'); const lastUpdate = this.safeInteger (order, 'last_update_timestamp'); const id = this.safeString (order, 'order_id'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); let lastTradeTimestamp = undefined; if (filled !== undefined) { if (filled > 0) { lastTradeTimestamp = lastUpdate; } } - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = price * filled; - } - } const status = this.parseOrderStatus (this.safeString (order, 'order_state')); const marketId = this.safeString (order, 'instrument_name'); market = this.safeMarket (marketId, market); const side = this.safeStringLower (order, 'direction'); - let feeCost = this.safeFloat (order, 'commission'); + let feeCost = this.safeNumber (order, 'commission'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); @@ -61056,7 +60716,7 @@ module.exports = class deribit extends Exchange { const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); const stopPrice = this.safeValue (order, 'stop_price'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -61071,14 +60731,14 @@ module.exports = class deribit extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -61155,7 +60815,7 @@ module.exports = class deribit extends Exchange { } } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price or stopPrice param for a ' + type + ' order'); } else { @@ -61554,7 +61214,7 @@ module.exports = class deribit extends Exchange { const updated = this.safeInteger (transaction, 'updated_timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let type = 'deposit'; let fee = undefined; if (feeCost !== undefined) { @@ -61577,7 +61237,7 @@ module.exports = class deribit extends Exchange { 'tagTo': undefined, 'tagFrom': undefined, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -61623,7 +61283,7 @@ module.exports = class deribit extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.codeFromOptions ('fetchPositions'); const currency = this.currency (code); @@ -61744,13 +61404,14 @@ module.exports = class deribit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],78:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],77:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); -const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -61808,11 +61469,6 @@ module.exports = class digifinex extends Exchange { 'referral': 'https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp', }, 'api': { - 'v2': { - 'get': [ - 'ticker', - ], - }, 'public': { 'get': [ '{market}/symbols', @@ -61938,6 +61594,7 @@ module.exports = class digifinex extends Exchange { }, 'commonCurrencies': { 'BHT': 'Black House Test', + 'EPS': 'Epanus', 'MBN': 'Mobilian Coin', 'TEL': 'TEL666', }, @@ -61992,7 +61649,7 @@ module.exports = class digifinex extends Exchange { const depositStatus = this.safeValue (currency, 'deposit_status', 1); const withdrawStatus = this.safeValue (currency, 'withdraw_status', 1); const active = depositStatus && withdrawStatus; - const fee = this.safeFloat (currency, 'withdraw_fee_rate'); + const fee = this.safeNumber (currency, 'withdraw_fee_rate'); if (code in result) { if (Array.isArray (result[code]['info'])) { result[code]['info'].push (currency); @@ -62023,7 +61680,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw_amount'), + 'min': this.safeNumber (currency, 'min_withdraw_amount'), 'max': undefined, }, }, @@ -62077,7 +61734,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), 'max': undefined, }, 'price': { @@ -62085,7 +61742,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), + 'min': this.safeNumber (market, 'minimum_value'), 'max': undefined, }, }; @@ -62099,7 +61756,7 @@ module.exports = class digifinex extends Exchange { // const status = this.safeString (market, 'status'); // const active = (status === 'TRADING'); // - const isAllowed = this.safeValue (market, 'is_allow', 1); + const isAllowed = this.safeInteger (market, 'is_allow', 1); const active = isAllowed ? true : false; const type = 'spot'; const spot = (type === 'spot'); @@ -62155,7 +61812,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), + 'min': this.safeNumber (market, 'min_volume'), 'max': undefined, }, 'price': { @@ -62163,7 +61820,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, }; @@ -62208,12 +61865,12 @@ module.exports = class digifinex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -62247,87 +61904,67 @@ module.exports = class digifinex extends Exchange { } async fetchTickers (symbols = undefined, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTickers() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); - const request = { - 'apiKey': apiKey, - }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (params); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const result = {}; - const tickers = this.safeValue (response, 'ticker', {}); + const tickers = this.safeValue (response, 'ticker', []); const date = this.safeInteger (response, 'date'); - const reversedMarketIds = Object.keys (tickers); - for (let i = 0; i < reversedMarketIds.length; i++) { - const reversedMarketId = reversedMarketIds[i]; - const ticker = this.extend ({ + for (let i = 0; i < tickers.length; i++) { + const rawTicker = this.extend ({ 'date': date, - }, tickers[reversedMarketId]); - const [ quoteId, baseId ] = reversedMarketId.split ('_'); - const marketId = baseId.toUpperCase () + '_' + quoteId.toUpperCase (); - const market = this.safeMarket (marketId, undefined, '_'); - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); + }, tickers[i]); + const ticker = this.parseTicker (rawTicker); + const symbol = ticker['symbol']; + result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTicker (symbol, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTicker() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); const market = this.market (symbol); - // reversed base/quote in v2 - const marketId = market['quoteId'].toLowerCase () + '_' + market['baseId'].toLowerCase (); const request = { - 'symbol': marketId, - 'apiKey': apiKey, + 'symbol': market['id'], }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (this.extend (request, params)); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const date = this.safeInteger (response, 'date'); - const ticker = this.safeValue (response, 'ticker', {}); - let result = this.safeValue (ticker, marketId, {}); - result = this.extend ({ 'date': date }, result); + const tickers = this.safeValue (response, 'ticker', []); + const firstTicker = this.safeValue (tickers, 0, {}); + const result = this.extend ({ 'date': date }, firstTicker); return this.parseTicker (result, market); } @@ -62337,6 +61974,7 @@ module.exports = class digifinex extends Exchange { // // { // "last":0.021957, + // "symbol": "btc_usdt", // "base_vol":2249.3521732227, // "change":-0.6, // "vol":102443.5111, @@ -62347,22 +61985,20 @@ module.exports = class digifinex extends Exchange { // "date"1564518452, // injected from fetchTicker/fetchTickers // } // - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeStringUpper (ticker, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -62372,8 +62008,8 @@ module.exports = class digifinex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'base_vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'base_vol'), 'info': ticker, }; } @@ -62409,18 +62045,15 @@ module.exports = class digifinex extends Exchange { const orderId = this.safeString (trade, 'order_id'); const timestamp = this.safeTimestamp2 (trade, 'date', 'timestamp'); const side = this.safeString2 (trade, 'type', 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); const takerOrMaker = this.safeValue (trade, 'is_maker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -62522,11 +62155,11 @@ module.exports = class digifinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 5), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 1), // volume + this.safeNumber (ohlcv, 5), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 1), // volume ]; } @@ -62717,21 +62350,11 @@ module.exports = class digifinex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_price'); - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - return { + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -62747,13 +62370,13 @@ module.exports = class digifinex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'average': average, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -62947,7 +62570,7 @@ module.exports = class digifinex extends Exchange { const code = this.safeCurrencyCode (this.safeString (item, 'currency_mark'), currency); const timestamp = this.safeTimestamp (item, 'time'); const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -63010,16 +62633,6 @@ module.exports = class digifinex extends Exchange { return this.parseLedger (items, currency, since, limit); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -63172,8 +62785,8 @@ module.exports = class digifinex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_date')); const updated = this.parse8601 (this.safeString (transaction, 'finished_date')); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -63223,7 +62836,7 @@ module.exports = class digifinex extends Exchange { } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const version = (api === 'v2') ? api : this.version; + const version = this.version; let url = this.urls['api'] + '/' + version + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); const urlencoded = this.urlencode (this.keysort (query)); @@ -63275,1283 +62888,7 @@ module.exports = class digifinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],79:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, BadRequest, InsufficientFunds, PermissionDenied, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class dsx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'dsx', - 'name': 'DSX', - 'countries': [ 'UK' ], - 'rateLimit': 1500, - 'version': 'v3', - 'has': { - 'cancelOrder': true, - 'CORS': false, - 'createDepositAddress': true, - 'createMarketOrder': false, - 'createOrder': true, - 'fetchBalance': true, - 'fetchClosedOrders': false, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOHLCV': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchOrderBooks': true, - 'fetchOrders': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTransactions': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg', - 'api': { - 'public': 'https://dsxglobal.com/mapi', // market data - 'private': 'https://dsxglobal.com/tapi', // trading - 'dwapi': 'https://dsxglobal.com/dwapi', // deposit/withdraw - }, - 'www': 'https://dsxglobal.com', - 'doc': [ - 'https://dsxglobal.com/developers/publicApi', - ], - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'maker': 0.15 / 100, - 'taker': 0.25 / 100, - }, - }, - 'timeframes': { - '1m': 'm', - '1h': 'h', - '1d': 'd', - }, - 'api': { - // market data (public) - 'public': { - 'get': [ - 'barsFromMoment/{pair}/{period}/{start}', - 'depth/{pair}', - 'info', - 'lastBars/{pair}/{period}/{amount}', // period is 'm', 'h' or 'd' - 'periodBars/{pair}/{period}/{start}/{end}', - 'ticker/{pair}', - 'trades/{pair}', - ], - }, - // trading (private) - 'private': { - 'post': [ - 'info/account', - 'history/transactions', - 'history/trades', - 'history/orders', - 'orders', - 'order/cancel', - // 'order/cancel/all', - 'order/status', - 'order/new', - 'volume', - 'fees', // trading fee schedule - ], - }, - // deposit / withdraw (private) - 'dwapi': { - 'post': [ - 'deposit/cryptoaddress', - 'withdraw/crypto', - 'withdraw/fiat', - 'withdraw/submit', - // 'withdraw/cancel', - 'transaction/status', // see 'history/transactions' in private tapi above - ], - }, - }, - 'exceptions': { - 'exact': { - 'Sign is invalid': AuthenticationError, // {"success":0,"error":"Sign is invalid"} - 'Order was rejected. Incorrect price.': InvalidOrder, // {"success":0,"error":"Order was rejected. Incorrect price."} - "Order was rejected. You don't have enough money.": InsufficientFunds, // {"success":0,"error":"Order was rejected. You don't have enough money."} - 'This method is blocked for your pair of keys': PermissionDenied, // {"success":0,"error":"This method is blocked for your pair of keys"} - }, - 'broad': { - 'INVALID_PARAMETER': BadRequest, - 'Invalid pair name': ExchangeError, // {"success":0,"error":"Invalid pair name: btc_eth"} - 'invalid api key': AuthenticationError, - 'invalid sign': AuthenticationError, - 'api key dont have trade permission': AuthenticationError, - 'invalid parameter': InvalidOrder, - 'invalid order': InvalidOrder, - 'Requests too often': DDoSProtection, - 'not available': ExchangeNotAvailable, - 'data unavailable': ExchangeNotAvailable, - 'external service unavailable': ExchangeNotAvailable, - 'nonce is invalid': InvalidNonce, // {"success":0,"error":"Parameter: nonce is invalid"} - 'Incorrect volume': InvalidOrder, // {"success": 0,"error":"Order was rejected. Incorrect volume."} - }, - }, - 'options': { - 'fetchTickersMaxLength': 250, - }, - 'commonCurrencies': { - 'DSH': 'DASH', - }, - }); - } - - async fetchMarkets (params = {}) { - const response = await this.publicGetInfo (params); - // - // { - // "server_time": 1522057909, - // "pairs": { - // "ethusd": { - // "decimal_places": 5, - // "min_price": 100, - // "max_price": 1500, - // "min_amount": 0.01, - // "hidden": 0, - // "fee": 0, - // "amount_decimal_places": 4, - // "quoted_currency": "USD", - // "base_currency": "ETH" - // } - // } - // } - // - const markets = this.safeValue (response, 'pairs'); - const keys = Object.keys (markets); - const result = []; - for (let i = 0; i < keys.length; i++) { - const id = keys[i]; - const market = markets[id]; - const baseId = this.safeString (market, 'base_currency'); - const quoteId = this.safeString (market, 'quoted_currency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const precision = { - 'amount': this.safeInteger (market, 'decimal_places'), - 'price': this.safeInteger (market, 'decimal_places'), - }; - const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), - }; - const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), - }; - const costLimits = { - 'min': this.safeFloat (market, 'min_total'), - }; - const limits = { - 'amount': amountLimits, - 'price': priceLimits, - 'cost': costLimits, - }; - const hidden = this.safeInteger (market, 'hidden'); - const active = (hidden === 0); - // see parseMarket below - // https://github.com/ccxt/ccxt/pull/5786 - const otherId = base.toLowerCase () + quote.toLowerCase (); - result.push ({ - 'id': id, - 'otherId': otherId, // https://github.com/ccxt/ccxt/pull/5786 - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': active, - 'precision': precision, - 'limits': limits, - 'info': market, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostInfoAccount (); - // - // { - // "success" : 1, - // "return" : { - // "funds" : { - // "BTC" : { - // "total" : 0, - // "available" : 0 - // }, - // "USD" : { - // "total" : 0, - // "available" : 0 - // }, - // "USDT" : { - // "total" : 0, - // "available" : 0 - // } - // }, - // "rights" : { - // "info" : 1, - // "trade" : 1 - // }, - // "transactionCount" : 0, - // "openOrders" : 0, - // "serverTime" : 1537451465 - // } - // } - // - const balances = this.safeValue (response, 'return'); - const result = { 'info': response }; - const funds = this.safeValue (balances, 'funds'); - const currencyIds = Object.keys (funds); - for (let i = 0; i < currencyIds.length; i++) { - const currencyId = currencyIds[i]; - const code = this.safeCurrencyCode (currencyId); - const balance = this.safeValue (funds, currencyId, {}); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseTicker (ticker, market = undefined) { - // - // { high: 0.03492, - // low: 0.03245, - // avg: 29.46133, - // vol: 500.8661, - // vol_cur: 17.000797104, - // last: 0.03364, - // buy: 0.03362, - // sell: 0.03381, - // updated: 1537521993, - // pair: "ethbtc" } - // - const timestamp = this.safeTimestamp (ticker, 'updated'); - let symbol = undefined; - const marketId = this.safeString (ticker, 'pair'); - market = this.parseMarket (marketId); - if (market !== undefined) { - symbol = market['symbol']; - } - // dsx average is inverted, liqui average is not - let average = this.safeFloat (ticker, 'avg'); - if (average !== undefined) { - if (average > 0) { - average = 1 / average; - } - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_cur'), - 'info': ticker, - }; - } - - parseTrade (trade, market = undefined) { - // - // fetchTrades (public) - // - // { - // "amount" : 0.0128, - // "price" : 6483.99000, - // "timestamp" : 1540334614, - // "tid" : 35684364, - // "type" : "ask" - // } - // - // fetchMyTrades (private) - // - // { - // "number": "36635882", // <-- this is present if the trade has come from the '/order/status' call - // "id": "36635882", // <-- this may have been artifically added by the parseTrades method - // "pair": "btcusd", - // "type": "buy", - // "volume": 0.0595, - // "rate": 9750, - // "orderId": 77149299, - // "timestamp": 1519612317, - // "commission": 0.00020825, - // "commissionCurrency": "btc" - // } - // - const timestamp = this.safeTimestamp (trade, 'timestamp'); - let side = this.safeString (trade, 'type'); - if (side === 'ask') { - side = 'sell'; - } else if (side === 'bid') { - side = 'buy'; - } - const price = this.safeFloat2 (trade, 'rate', 'price'); - const id = this.safeString2 (trade, 'number', 'id'); - const orderId = this.safeString (trade, 'orderId'); - const marketId = this.safeString (trade, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const amount = this.safeFloat2 (trade, 'amount', 'volume'); - const type = 'limit'; // all trades are still limit trades - let takerOrMaker = undefined; - let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const isYourOrder = this.safeValue (trade, 'is_your_order'); - if (isYourOrder !== undefined) { - takerOrMaker = 'taker'; - if (isYourOrder) { - takerOrMaker = 'maker'; - } - if (fee === undefined) { - fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); - } - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - return { - 'id': id, - 'order': orderId, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': type, - 'side': side, - 'takerOrMaker': takerOrMaker, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - 'info': trade, - }; - } - - parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - let result = []; - if (Array.isArray (trades)) { - for (let i = 0; i < trades.length; i++) { - result.push (this.parseTrade (trades[i], market)); - } - } else { - const ids = Object.keys (trades); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const trade = this.parseTrade (trades[id], market); - result.push (this.extend (trade, { 'id': id }, params)); - } - } - result = this.sortBy (result, 'timestamp'); - const symbol = (market !== undefined) ? market['symbol'] : undefined; - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const market_id_in_reponse = (market['id'] in response); - if (!market_id_in_reponse) { - throw new ExchangeError (this.id + ' ' + market['symbol'] + ' order book is empty or not available'); - } - const orderbook = response[market['id']]; - return this.parseOrderBook (orderbook); - } - - async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let ids = undefined; - if (symbols === undefined) { - ids = this.ids.join ('-'); - // max URL length is 2083 symbols, including http schema, hostname, tld, etc... - if (ids.length > 2048) { - const numIds = this.ids.length; - throw new ExchangeError (this.id + ' has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const result = {}; - ids = Object.keys (response); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let symbol = id; - if (id in this.markets_by_id) { - const market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseOrderBook (response[id]); - } - return result; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - let ids = this.ids; - if (symbols === undefined) { - const numIds = ids.length; - ids = ids.join ('-'); - const maxLength = this.safeInteger (this.options, 'fetchTickersMaxLength', 2048); - // max URL length is 2048 symbols, including http schema, hostname, tld, etc... - if (ids.length > this.options['fetchTickersMaxLength']) { - throw new ArgumentsRequired (this.id + ' has ' + numIds.toString () + ' markets exceeding max URL length for this endpoint (' + maxLength.toString () + ' characters), please, specify a list of symbols of interest in the first argument to fetchTickers'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - const tickers = await this.publicGetTickerPair (this.extend (request, params)); - // - // { - // "bchbtc" : { - // "high" : 0.02989, - // "low" : 0.02736, - // "avg" : 33.90585, - // "vol" : 0.65982205, - // "vol_cur" : 0.0194604180960, - // "last" : 0.03000, - // "buy" : 0.02980, - // "sell" : 0.03001, - // "updated" : 1568104614, - // "pair" : "bchbtc" - // }, - // "ethbtc" : { - // "high" : 0.01772, - // "low" : 0.01742, - // "avg" : 56.89082, - // "vol" : 229.247115044, - // "vol_cur" : 4.02959737298943, - // "last" : 0.01769, - // "buy" : 0.01768, - // "sell" : 0.01776, - // "updated" : 1568104614, - // "pair" : "ethbtc" - // } - // } - // - const result = {}; - const keys = Object.keys (tickers); - for (let k = 0; k < keys.length; k++) { - const id = keys[k]; - const ticker = tickers[id]; - let symbol = id; - let market = undefined; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseTicker (ticker, market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - const tickers = await this.fetchTickers ([ symbol ], params); - return tickers[symbol]; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; - } - const response = await this.publicGetTradesPair (this.extend (request, params)); - if (Array.isArray (response)) { - const numElements = response.length; - if (numElements === 0) { - return []; - } - } - return this.parseTrades (response[market['id']], market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // } - // - return [ - this.safeInteger (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - 'period': this.timeframes[timeframe], - }; - let method = 'publicGetLastBarsPairPeriodAmount'; - if (since === undefined) { - if (limit === undefined) { - limit = 100; // required, max 2000 - } - request['amount'] = limit; - } else { - method = 'publicGetPeriodBarsPairPeriodStartEnd'; - // in their docs they expect milliseconds - // but it returns empty arrays with milliseconds - // however, it does work properly with seconds - request['start'] = parseInt (since / 1000); - if (limit === undefined) { - request['end'] = this.seconds (); - } else { - const duration = this.parseTimeframe (timeframe) * 1000; - const end = this.sum (since, duration * limit); - request['end'] = parseInt (end / 1000); - } - } - const response = await this[method] (this.extend (request, params)); - // - // { - // "ethbtc": [ - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // }, - // { - // "high" : 0.01967, - // "open" : 0.01967, - // "low" : 0.01967, - // "close" : 0.01967, - // "amount" : 0, - // "timestamp" : 1565155680000 - // } - // ] - // } - // - const candles = this.safeValue (response, market['id'], []); - return this.parseOHLCVs (candles, market, timeframe, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (type === 'market' && price === undefined) { - throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument even for market orders, that is the worst price that you agree to fill your order for'); - } - const request = { - 'pair': market['id'], - 'type': side, - 'volume': this.amountToPrecision (symbol, amount), - 'rate': this.priceToPrecision (symbol, price), - 'orderType': type, - }; - price = parseFloat (price); - amount = parseFloat (amount); - const response = await this.privatePostOrderNew (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "received": 0, - // "remains": 10, - // "funds": { - // "BTC": { - // "total": 100, - // "available": 95 - // }, - // "USD": { - // "total": 10000, - // "available": 9995 - // }, - // "EUR": { - // "total": 1000, - // "available": 995 - // }, - // "LTC": { - // "total": 1000, - // "available": 995 - // } - // }, - // "orderId": 0, // https://github.com/ccxt/ccxt/issues/3677 - // } - // } - // - let status = 'open'; - let filled = 0.0; - let remaining = amount; - const responseReturn = this.safeValue (response, 'return'); - let id = this.safeString2 (responseReturn, 'orderId', 'order_id'); - if (id === '0') { - id = this.safeString (responseReturn, 'initOrderId', 'init_order_id'); - status = 'closed'; - } - filled = this.safeFloat (responseReturn, 'received', 0.0); - remaining = this.safeFloat (responseReturn, 'remains', amount); - const timestamp = this.milliseconds (); - return { - 'info': response, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'side': side, - 'price': price, - 'cost': price * filled, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'fee': undefined, - // 'trades': this.parseTrades (order['trades'], market), - }; - } - - parseOrderStatus (status) { - const statuses = { - '0': 'open', // Active - '1': 'closed', // Filled - '2': 'canceled', // Killed - '3': 'canceling', // Killing - '7': 'canceled', // Rejected - }; - return this.safeString (statuses, status, status); - } - - parseMarket (id) { - if (id in this.markets_by_id) { - return this.markets_by_id[id]; - } else { - // the following is a fix for - // https://github.com/ccxt/ccxt/pull/5786 - // https://github.com/ccxt/ccxt/issues/5770 - let markets_by_other_id = this.safeValue (this.options, 'markets_by_other_id'); - if (markets_by_other_id === undefined) { - this.options['markets_by_other_id'] = this.indexBy (this.markets, 'otherId'); - markets_by_other_id = this.options['markets_by_other_id']; - } - if (id in markets_by_other_id) { - return markets_by_other_id[id]; - } - } - return undefined; - } - - parseOrder (order, market = undefined) { - // - // fetchOrder - // - // { - // "number": 36635882, - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // - const id = this.safeString (order, 'id'); - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const timestamp = this.safeTimestamp (order, 'timestampCreated'); - const marketId = this.safeString (order, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const remaining = this.safeFloat (order, 'remainingVolume'); - const amount = this.safeFloat (order, 'volume'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } - } - const orderType = this.safeString (order, 'orderType'); - const side = this.safeString (order, 'type'); - let fee = undefined; - const deals = this.safeValue (order, 'deals', []); - const numDeals = deals.length; - let trades = undefined; - let lastTradeTimestamp = undefined; - if (numDeals > 0) { - trades = this.parseTrades (deals); - let feeCost = undefined; - let feeCurrency = undefined; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - if (feeCost === undefined) { - feeCost = 0; - } - feeCost = this.sum (feeCost, trade['fee']['cost']); - feeCurrency = trade['fee']['currency']; - lastTradeTimestamp = trade['timestamp']; - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'type': orderType, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': undefined, - 'cost': cost, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'status': status, - 'fee': fee, - 'trades': trades, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': parseInt (id), - }; - const response = await this.privatePostOrderStatus (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // } - // - return this.parseOrder (this.extend ({ - 'id': id, - }, response['return'])); - } - - parseOrdersById (orders, symbol = undefined, since = undefined, limit = undefined) { - const ids = Object.keys (orders); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.parseOrder (this.extend ({ - 'id': id.toString (), - }, orders[id])); - result.push (order); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - const response = await this.privatePostOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': id, - }; - const response = await this.privatePostOrderCancel (this.extend (request, params)); - return response; - } - - parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { - const result = []; - const ids = Object.keys (orders); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.extend ({ 'id': id }, orders[id]); - result.push (this.extend (this.parseOrder (order, market), params)); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - const orders = await this.fetchOrders (symbol, since, limit, params); - return this.filterBy (orders, 'status', 'closed'); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let market = undefined; - // some derived classes use camelcase notation for request fields - const request = { - // 'from': 123456789, // trade ID, from which the display starts numerical 0 (test result: liqui ignores this field) - // 'count': 1000, // the number of trades for display numerical, default = 1000 - // 'from_id': trade ID, from which the display starts numerical 0 - // 'end_id': trade ID on which the display ends numerical ∞ - // 'order': 'ASC', // sorting, default = DESC (test result: liqui ignores this field, most recent trade always goes last) - // 'since': 1234567890, // UTC start time, default = 0 (test result: liqui ignores this field) - // 'end': 1234567890, // UTC end time, default = ∞ (test result: liqui ignores this field) - // 'pair': 'eth_btc', // default = all markets - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['pair'] = market['id']; - } - if (limit !== undefined) { - request['count'] = parseInt (limit); - } - if (since !== undefined) { - request['since'] = parseInt (since / 1000); - } - const response = await this.privatePostHistoryTrades (this.extend (request, params)); - let trades = []; - if ('return' in response) { - trades = response['return']; - } - return this.parseTrades (trades, market, since, limit); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let currency = undefined; - const request = {}; - if (code !== undefined) { - currency = this.currency (code); - request['currency'] = currency['id']; - } - if (since !== undefined) { - request['since'] = since; - } - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryTransactions (this.extend (request, params)); - // - // { - // "success": 1, - // "return": [ - // { - // "id": 1, - // "timestamp": 11, - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // ] - // } - // - const transactions = this.safeValue (response, 'return', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - '1': 'failed', - '2': 'ok', - '3': 'pending', - '4': 'failed', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // "id": 1, - // "timestamp": 11, // 11 in their docs ( - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // - const timestamp = this.safeTimestamp (transaction, 'timestamp'); - let type = this.safeString (transaction, 'type'); - if (type !== undefined) { - if (type === 'Incoming') { - type = 'deposit'; - } else if (type === 'Withdraw') { - type = 'withdrawal'; - } - } - const currencyId = this.safeString (transaction, 'currency'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - return { - 'id': this.safeString (transaction, 'id'), - 'txid': this.safeString (transaction, 'txid'), - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'address': this.safeString (transaction, 'address'), - 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), - 'currency': code, - 'status': status, - 'fee': { - 'currency': code, - 'cost': this.safeFloat (transaction, 'commission'), - 'rate': undefined, - }, - 'info': transaction, - }; - } - - async createDepositAddress (code, params = {}) { - const request = { - 'new': 1, - }; - const response = await this.fetchDepositAddress (code, this.extend (request, params)); - return response; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency': currency['id'], - }; - const response = await this.dwapiPostDepositCryptoaddress (this.extend (request, params)); - const result = this.safeValue (response, 'return', {}); - const address = this.safeString (result, 'address'); - this.checkAddress (address); - return { - 'currency': code, - 'address': address, - 'tag': undefined, // not documented in DSX API - 'info': response, - }; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - const commission = this.safeValue (params, 'commission'); - if (commission === undefined) { - throw new ArgumentsRequired (this.id + ' withdraw() requires a `commission` (withdrawal fee) parameter (string)'); - } - params = this.omit (params, commission); - const request = { - 'currency': currency['id'], - 'amount': parseFloat (amount), - 'address': address, - 'commission': commission, - }; - if (tag !== undefined) { - request['address'] += ':' + tag; - } - const response = await this.dwapiPostWithdrawCrypto (this.extend (request, params)); - // - // [ - // { - // "success": 1, - // "return": { - // "transactionId": 2863073 - // } - // } - // ] - // - const data = this.safeValue (response, 'return', {}); - const id = this.safeString (data, 'transactionId'); - return { - 'info': response, - 'id': id, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'][api]; - const query = this.omit (params, this.extractParams (path)); - if (api === 'private' || api === 'dwapi') { - url += '/' + this.version + '/' + this.implodeParams (path, params); - this.checkRequiredCredentials (); - const nonce = this.nonce (); - body = this.urlencode (this.extend ({ - 'nonce': nonce, - }, query)); - const signature = this.hmac (this.encode (body), this.encode (this.secret), 'sha512', 'base64'); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': signature, - }; - } else if (api === 'public') { - url += '/' + this.implodeParams (path, params); - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - url += '/' + this.implodeParams (path, params); - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - if (Object.keys (query).length) { - body = this.json (query); - headers = { - 'Content-Type': 'application/json', - }; - } - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - if ('success' in response) { - // - // 1 - Liqui only returns the integer 'success' key from their private API - // - // { "success": 1, ... } httpCode === 200 - // { "success": 0, ... } httpCode === 200 - // - // 2 - However, exchanges derived from Liqui, can return non-integers - // - // It can be a numeric string - // { "sucesss": "1", ... } - // { "sucesss": "0", ... }, httpCode >= 200 (can be 403, 502, etc) - // - // Or just a string - // { "success": "true", ... } - // { "success": "false", ... }, httpCode >= 200 - // - // Or a boolean - // { "success": true, ... } - // { "success": false, ... }, httpCode >= 200 - // - // 3 - Oversimplified, Python PEP8 forbids comparison operator (===) of different types - // - // 4 - We do not want to copy-paste and duplicate the code of this handler to other exchanges derived from Liqui - // - // To cover points 1, 2, 3 and 4 combined this handler should work like this: - // - let success = this.safeValue (response, 'success', false); - if (typeof success === 'string') { - if ((success === 'true') || (success === '1')) { - success = true; - } else { - success = false; - } - } - if (!success) { - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'error'); - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],80:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],78:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -64775,7 +63112,7 @@ module.exports = class equos extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeVol'), + 'min': this.safeNumber (market, 'minTradeVol'), 'max': undefined, }, 'price': { @@ -64841,7 +63178,7 @@ module.exports = class equos extends Exchange { const name = this.safeString (currency, 6); const status = this.safeInteger (currency, 4); const active = (status === 1); - const fee = this.safeFloat (currency, 5); // withdraw_fee + const fee = this.safeNumber (currency, 5); // withdraw_fee return { 'id': id, 'info': currency, @@ -64933,8 +63270,8 @@ module.exports = class equos extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); return [ this.convertFromScale (price, market['precision']['price']), this.convertFromScale (amount, market['precision']['amount']), @@ -65080,9 +63417,9 @@ module.exports = class equos extends Exchange { orderId = this.safeString (trade, 'orderId'); side = this.safeStringLower (trade, 'side'); type = this.parseOrderType (this.safeString (trade, 'ordType')); - price = this.safeFloat (trade, 'lastPx'); - amount = this.safeFloat (trade, 'quoteQty'); - let feeCost = this.safeFloat (trade, 'commission'); + price = this.safeNumber (trade, 'lastPx'); + amount = this.safeNumber (trade, 'quoteQty'); + let feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { feeCost = -feeCost; const feeCurrencyId = this.safeString (trade, 'commCurrency'); @@ -65153,8 +63490,8 @@ module.exports = class equos extends Exchange { if (assetType === 'ASSET') { const currencyId = this.safeString (position, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const quantity = this.safeFloat (position, 'quantity'); - const availableQuantity = this.safeFloat (position, 'availableQuantity'); + const quantity = this.safeNumber (position, 'quantity'); + const availableQuantity = this.safeNumber (position, 'availableQuantity'); const scale = this.safeInteger (position, 'quantity_scale'); const account = this.account (); account['free'] = this.convertFromScale (availableQuantity, scale); @@ -65200,7 +63537,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -65297,7 +63634,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -65670,7 +64007,7 @@ module.exports = class equos extends Exchange { address = undefined; } const type = this.safeString (transaction, 'type'); - let amount = this.safeFloat (transaction, 'balance_change'); + let amount = this.safeNumber (transaction, 'balance_change'); if (amount === undefined) { amount = this.safeInteger (transaction, 'quantity'); const amountScale = this.safeInteger (transaction, 'quantity_scale'); @@ -65753,8 +64090,8 @@ module.exports = class equos extends Exchange { for (let i = 0; i < tradingFees.length; i++) { const tradingFee = tradingFees[i]; if (this.safeString (tradingFee, 'tier') !== undefined) { - taker[tradingFee['tier']] = this.safeFloat (tradingFee, 'taker'); - maker[tradingFee['tier']] = this.safeFloat (tradingFee, 'maker'); + taker[tradingFee['tier']] = this.safeNumber (tradingFee, 'taker'); + maker[tradingFee['tier']] = this.safeNumber (tradingFee, 'maker'); } } return { @@ -65885,28 +64222,6 @@ module.exports = class equos extends Exchange { let remaining = this.safeInteger (order, 'leavesQty'); const remainingScale = this.safeInteger (order, 'leavesQty_scale'); remaining = this.convertFromScale (remaining, remainingScale); - if (remaining <= 0) { - if ((filled !== undefined) && (amount !== undefined) && (filled < amount)) { - remaining = undefined; - } - } - if ((remaining === undefined) && (amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0); - } - let average = this.safeInteger (order, 'price', 0); - if (average === 0) { - average = undefined; - } - const averageScale = this.safeInteger (order, 'price_scale'); - average = this.convertFromScale (average, averageScale); - let cost = undefined; - if (filled !== 0) { - if (average > 0) { - cost = average * filled; - } else if (price > 0) { - cost = price * filled; - } - } let fee = undefined; const currencyId = this.safeInteger (order, 'feeInstrumentId'); const feeCurrencyCode = this.safeCurrencyCode (currencyId); @@ -65929,7 +64244,7 @@ module.exports = class equos extends Exchange { } const stopPriceScale = this.safeInteger (order, 'stopPx_scale', 0); const stopPrice = this.convertFromScale (this.safeInteger (order, 'stopPx'), stopPriceScale); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -65944,14 +64259,14 @@ module.exports = class equos extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -66101,7 +64416,7 @@ module.exports = class equos extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],81:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],79:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -66109,6 +64424,7 @@ module.exports = class equos extends Exchange { const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, InvalidOrder, ExchangeError, BadRequest, BadSymbol } = require ('./base/errors'); const { TRUNCATE, SIGNIFICANT_DIGITS } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -66321,7 +64637,7 @@ module.exports = class eterbase extends Exchange { const rule = rules[i]; const attribute = this.safeString (rule, 'attribute'); const condition = this.safeString (rule, 'condition'); - const value = this.safeFloat (rule, 'value'); + const value = this.safeNumber (rule, 'value'); if ((attribute === 'Qty') && (condition === 'Min')) { minAmount = value; } else if ((attribute === 'Qty') && (condition === 'Max')) { @@ -66411,7 +64727,7 @@ module.exports = class eterbase extends Exchange { 'type': type, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -66427,8 +64743,8 @@ module.exports = class eterbase extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMin'), - 'max': this.safeFloat (currency, 'withdrawalMax'), + 'min': this.safeNumber (currency, 'withdrawalMin'), + 'max': this.safeNumber (currency, 'withdrawalMax'), }, }, }; @@ -66455,17 +64771,17 @@ module.exports = class eterbase extends Exchange { const marketId = this.safeString (ticker, 'marketId'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const last = this.safeFloat (ticker, 'price'); - const baseVolume = this.safeFloat (ticker, 'volumeBase'); - const quoteVolume = this.safeFloat (ticker, 'volume'); + const last = this.safeNumber (ticker, 'price'); + const baseVolume = this.safeNumber (ticker, 'volumeBase'); + const quoteVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const percentage = this.safeFloat (ticker, 'change'); + const percentage = this.safeNumber (ticker, 'change'); const result = { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -66507,14 +64823,6 @@ module.exports = class eterbase extends Exchange { return this.parseTicker (response, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { @@ -66569,10 +64877,12 @@ module.exports = class eterbase extends Exchange { // "filledAt": 1556355722341 // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -66581,9 +64891,9 @@ module.exports = class eterbase extends Exchange { 'currency': feeCurrencyCode, }; } - let cost = this.safeFloat (trade, 'qty'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + let cost = this.safeNumber (trade, 'qty'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger2 (trade, 'executedAt', 'filledAt'); const tradeSide = this.safeString (trade, 'side'); @@ -66681,11 +64991,11 @@ module.exports = class eterbase extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -66748,14 +65058,13 @@ module.exports = class eterbase extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetId'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'reserved'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -66882,18 +65191,18 @@ module.exports = class eterbase extends Exchange { } else { type = 'stoplimit'; } - let price = this.safeFloat (order, 'limitPrice'); - const amount = this.safeFloat (order, 'qty'); - let remaining = this.safeFloat (order, 'remainingQty'); + let price = this.safeNumber (order, 'limitPrice'); + const amount = this.safeNumber (order, 'qty'); + let remaining = this.safeNumber (order, 'remainingQty'); let filled = undefined; - const remainingCost = this.safeFloat (order, 'remainingCost'); + const remainingCost = this.safeNumber (order, 'remainingCost'); if ((remainingCost !== undefined) && (remainingCost === 0.0)) { remaining = 0; } if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); } - const cost = this.safeFloat (order, 'cost'); + const cost = this.safeNumber (order, 'cost'); if (type === 'market') { if (price === 0.0) { if ((cost !== undefined) && (filled !== undefined)) { @@ -66910,7 +65219,7 @@ module.exports = class eterbase extends Exchange { } } const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -67083,7 +65392,7 @@ module.exports = class eterbase extends Exchange { } if ((uppercaseType === 'MARKET') && (uppercaseSide === 'BUY')) { // for market buy it requires the amount of quote currency to spend - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); if (this.options['createMarketBuyOrderRequiresPrice']) { if (cost === undefined) { if (price !== undefined) { @@ -67246,7 +65555,7 @@ module.exports = class eterbase extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],82:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],80:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -67361,6 +65670,7 @@ module.exports = class exmo extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.2 / 100, @@ -67830,18 +66140,18 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = marketId.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const maxAmount = this.safeFloat (limit, 'max_q'); - const maxPrice = this.safeFloat (limit, 'max_p'); - const maxCost = this.safeFloat (limit, 'max_a'); - const minAmount = this.safeFloat (limit, 'min_q'); - const minPrice = this.safeFloat (limit, 'min_p'); - const minCost = this.safeFloat (limit, 'min_a'); - minAmounts[base] = Math.min (this.safeFloat (minAmounts, base, minAmount), minAmount); - maxAmounts[base] = Math.max (this.safeFloat (maxAmounts, base, maxAmount), maxAmount); - minPrices[quote] = Math.min (this.safeFloat (minPrices, quote, minPrice), minPrice); - minCosts[quote] = Math.min (this.safeFloat (minCosts, quote, minCost), minCost); - maxPrices[quote] = Math.max (this.safeFloat (maxPrices, quote, maxPrice), maxPrice); - maxCosts[quote] = Math.max (this.safeFloat (maxCosts, quote, maxCost), maxCost); + const maxAmount = this.safeNumber (limit, 'max_q'); + const maxPrice = this.safeNumber (limit, 'max_p'); + const maxCost = this.safeNumber (limit, 'max_a'); + const minAmount = this.safeNumber (limit, 'min_q'); + const minPrice = this.safeNumber (limit, 'min_p'); + const minCost = this.safeNumber (limit, 'min_a'); + minAmounts[base] = Math.min (this.safeNumber (minAmounts, base, minAmount), minAmount); + maxAmounts[base] = Math.max (this.safeNumber (maxAmounts, base, maxAmount), maxAmount); + minPrices[quote] = Math.min (this.safeNumber (minPrices, quote, minPrice), minPrice); + minCosts[quote] = Math.min (this.safeNumber (minCosts, quote, minCost), minCost); + maxPrices[quote] = Math.max (this.safeNumber (maxPrices, quote, maxPrice), maxPrice); + maxCosts[quote] = Math.max (this.safeNumber (maxCosts, quote, maxCost), maxCost); } const result = {}; for (let i = 0; i < ids.length; i++) { @@ -67858,16 +66168,16 @@ module.exports = class exmo extends Exchange { 'precision': 8, 'limits': { 'amount': { - 'min': this.safeFloat (minAmounts, code), - 'max': this.safeFloat (maxAmounts, code), + 'min': this.safeNumber (minAmounts, code), + 'max': this.safeNumber (maxAmounts, code), }, 'price': { - 'min': this.safeFloat (minPrices, code), - 'max': this.safeFloat (maxPrices, code), + 'min': this.safeNumber (minPrices, code), + 'max': this.safeNumber (maxPrices, code), }, 'cost': { - 'min': this.safeFloat (minCosts, code), - 'max': this.safeFloat (maxCosts, code), + 'min': this.safeNumber (minCosts, code), + 'max': this.safeNumber (maxCosts, code), }, }, 'info': id, @@ -67902,8 +66212,8 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = symbol.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const taker = this.safeFloat (market, 'commission_taker_percent'); - const maker = this.safeFloat (market, 'commission_maker_percent'); + const taker = this.safeNumber (market, 'commission_taker_percent'); + const maker = this.safeNumber (market, 'commission_maker_percent'); result.push ({ 'id': id, 'symbol': symbol, @@ -67916,16 +66226,16 @@ module.exports = class exmo extends Exchange { 'maker': maker / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, }, 'precision': { @@ -67998,11 +66308,11 @@ module.exports = class exmo extends Exchange { // return [ this.safeInteger (ohlcv, 't'), - this.safeFloat (ohlcv, 'o'), - this.safeFloat (ohlcv, 'h'), - this.safeFloat (ohlcv, 'l'), - this.safeFloat (ohlcv, 'c'), - this.safeFloat (ohlcv, 'v'), + this.safeNumber (ohlcv, 'o'), + this.safeNumber (ohlcv, 'h'), + this.safeNumber (ohlcv, 'l'), + this.safeNumber (ohlcv, 'c'), + this.safeNumber (ohlcv, 'v'), ]; } @@ -68018,14 +66328,14 @@ module.exports = class exmo extends Exchange { const currencyId = this.currencyId (code); const account = this.account (); if (currencyId in free) { - account['free'] = this.safeFloat (free, currencyId); + account['free'] = this.safeString (free, currencyId); } if (currencyId in used) { - account['used'] = this.safeFloat (used, currencyId); + account['used'] = this.safeString (used, currencyId); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -68083,16 +66393,16 @@ module.exports = class exmo extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -68101,9 +66411,9 @@ module.exports = class exmo extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_curr'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'vol_curr'), 'info': ticker, }; } @@ -68164,9 +66474,9 @@ module.exports = class exmo extends Exchange { let symbol = undefined; const id = this.safeString (trade, 'trade_id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'quantity'); + const cost = this.safeNumber (trade, 'amount'); const side = this.safeString (trade, 'type'); const type = undefined; const marketId = this.safeString (trade, 'pair'); @@ -68185,11 +66495,11 @@ module.exports = class exmo extends Exchange { } const takerOrMaker = this.safeString (trade, 'exec_type'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission_amount'); + const feeCost = this.safeNumber (trade, 'commission_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commission_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (trade, 'commission_percent'); + let feeRate = this.safeNumber (trade, 'commission_percent'); if (feeRate !== undefined) { feeRate /= 1000; } @@ -68488,13 +66798,13 @@ module.exports = class exmo extends Exchange { market = this.markets_by_id[marketId]; } } - let amount = this.safeFloat (order, 'quantity'); + let amount = this.safeNumber (order, 'quantity'); if (amount === undefined) { const amountField = (side === 'buy') ? 'in_amount' : 'out_amount'; - amount = this.safeFloat (order, amountField); + amount = this.safeNumber (order, amountField); } - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'amount'); + let price = this.safeNumber (order, 'price'); + let cost = this.safeNumber (order, 'amount'); let filled = 0.0; const trades = []; const transactions = this.safeValue (order, 'trades', []); @@ -68615,24 +66925,6 @@ module.exports = class exmo extends Exchange { return undefined; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -68677,7 +66969,7 @@ module.exports = class exmo extends Exchange { // } // const timestamp = this.safeTimestamp (transaction, 'dt'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -68707,7 +66999,7 @@ module.exports = class exmo extends Exchange { // fixed funding fees only (for now) if (!this.fees['funding']['percentage']) { const key = (type === 'withdrawal') ? 'withdraw' : 'deposit'; - let feeCost = this.safeFloat (this.options['fundingFees'][key], code); + let feeCost = this.safeNumber (this.options['fundingFees'][key], code); // users don't pay for cashbacks, no fees for that const provider = this.safeString (transaction, 'provider'); if (provider === 'cashback') { @@ -68854,13 +67146,14 @@ module.exports = class exmo extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],83:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],81:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ExchangeNotAvailable, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -69005,26 +67298,26 @@ module.exports = class exx extends Exchange { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); ticker = ticker['ticker']; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'riseRate'), + 'change': this.safeNumber (ticker, 'riseRate'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -69074,14 +67367,11 @@ module.exports = class exx extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -69126,14 +67416,13 @@ module.exports = class exx extends Exchange { const currencyId = currencies[i]; const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'balance'), - 'used': this.safeFloat (balance, 'freeze'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -69153,11 +67442,10 @@ module.exports = class exx extends Exchange { // const symbol = market['symbol']; const timestamp = parseInt (order['trade_date']); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'trade_money'); - const amount = this.safeFloat (order, 'total_amount'); - const filled = this.safeFloat (order, 'trade_amount', 0.0); - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'trade_money'); + const amount = this.safeNumber (order, 'total_amount'); + const filled = this.safeNumber (order, 'trade_amount', 0.0); let status = this.safeInteger (order, 'status'); if (status === 1) { status = 'canceled'; @@ -69169,11 +67457,11 @@ module.exports = class exx extends Exchange { let fee = undefined; if ('fees' in order) { fee = { - 'cost': this.safeFloat (order, 'fees'), + 'cost': this.safeNumber (order, 'fees'), 'currency': market['quote'], }; } - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -69190,12 +67478,12 @@ module.exports = class exx extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -69320,13 +67608,14 @@ module.exports = class exx extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],84:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],82:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, ArgumentsRequired, InsufficientFunds, InvalidOrder, RateLimitExceeded, InvalidNonce, AuthenticationError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -69546,8 +67835,8 @@ module.exports = class fcoin extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'limit_amount_min'), - 'max': this.safeFloat (market, 'limit_amount_max'), + 'min': this.safeNumber (market, 'limit_amount_min'), + 'max': this.safeNumber (market, 'limit_amount_max'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -69642,12 +67931,12 @@ module.exports = class fcoin extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidsAsks (orders, priceKey = 0, amountKey = 1) { @@ -69660,8 +67949,8 @@ module.exports = class fcoin extends Exchange { const priceField = this.sum (index, priceKey); const amountField = this.sum (index, amountKey); result.push ([ - this.safeFloat (orders, priceField), - this.safeFloat (orders, amountField), + this.safeNumber (orders, priceField), + this.safeNumber (orders, amountField), ]); } return result; @@ -69709,17 +67998,17 @@ module.exports = class fcoin extends Exchange { } } const values = ticker['ticker']; - const last = this.safeFloat (values, 0); + const last = this.safeNumber (values, 0); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (values, 7), - 'low': this.safeFloat (values, 8), - 'bid': this.safeFloat (values, 2), - 'bidVolume': this.safeFloat (values, 3), - 'ask': this.safeFloat (values, 4), - 'askVolume': this.safeFloat (values, 5), + 'high': this.safeNumber (values, 7), + 'low': this.safeNumber (values, 8), + 'bid': this.safeNumber (values, 2), + 'bidVolume': this.safeNumber (values, 3), + 'ask': this.safeNumber (values, 4), + 'askVolume': this.safeNumber (values, 5), 'vwap': undefined, 'open': undefined, 'close': last, @@ -69728,8 +68017,8 @@ module.exports = class fcoin extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (values, 9), - 'quoteVolume': this.safeFloat (values, 10), + 'baseVolume': this.safeNumber (values, 9), + 'quoteVolume': this.safeNumber (values, 10), 'info': ticker, }; } @@ -69742,14 +68031,11 @@ module.exports = class fcoin extends Exchange { const timestamp = this.safeInteger (trade, 'ts'); const side = this.safeStringLower (trade, 'side'); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = undefined; return { 'id': id, @@ -69874,38 +68160,25 @@ module.exports = class fcoin extends Exchange { const symbol = market['symbol']; const orderType = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'created_at'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'executed_value'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'executed_value'); let feeCurrency = undefined; let feeCost = undefined; - const feeRebate = this.safeFloat (order, 'fees_income'); + const feeRebate = this.safeNumber (order, 'fees_income'); if ((feeRebate !== undefined) && (feeRebate > 0)) { if (market !== undefined) { feeCurrency = (side === 'buy') ? market['quote'] : market['base']; } feeCost = -feeRebate; } else { - feeCost = this.safeFloat (order, 'fill_fees'); + feeCost = this.safeNumber (order, 'fill_fees'); if (market !== undefined) { feeCurrency = (side === 'buy') ? market['base'] : market['quote']; } } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -69921,7 +68194,7 @@ module.exports = class fcoin extends Exchange { 'stopPrice': undefined, 'cost': cost, 'amount': amount, - 'remaining': remaining, + 'remaining': undefined, 'filled': filled, 'average': undefined, 'status': status, @@ -69930,7 +68203,7 @@ module.exports = class fcoin extends Exchange { 'currency': feeCurrency, }, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -69972,11 +68245,11 @@ module.exports = class fcoin extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_vol'), ]; } @@ -70065,7 +68338,7 @@ module.exports = class fcoin extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],85:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],83:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -70091,13 +68364,14 @@ module.exports = class fcoinjp extends fcoin { } }; -},{"./fcoin.js":84}],86:[function(require,module,exports){ +},{"./fcoin.js":82}],84:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70225,11 +68499,11 @@ module.exports = class flowbtc extends Exchange { const currencyId = balance['name']; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['total'] = this.safeFloat (balance, 'hold'); + account['free'] = this.safeString (balance, 'balance'); + account['total'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -70250,16 +68524,16 @@ module.exports = class flowbtc extends Exchange { }; const ticker = await this.publicPostGetTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -70269,8 +68543,8 @@ module.exports = class flowbtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume24hr'), - 'quoteVolume': this.safeFloat (ticker, 'volume24hrProduct2'), + 'baseVolume': this.safeNumber (ticker, 'volume24hr'), + 'quoteVolume': this.safeNumber (ticker, 'volume24hrProduct2'), 'info': ticker, }; } @@ -70279,14 +68553,11 @@ module.exports = class flowbtc extends Exchange { const timestamp = this.safeTimestamp (trade, 'unixtime'); const side = (trade['incomingOrderSide'] === 0) ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'px'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'px'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'timestamp': timestamp, @@ -70377,13 +68648,14 @@ module.exports = class flowbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],87:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],85:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70469,11 +68741,11 @@ module.exports = class foxbit extends Exchange { // otherwise we will lose the info if the currency balance has been funded or traded or not if (currencyId in balances) { const account = this.account (); - let used = this.safeFloat (balances, currencyId + '_locked'); + let used = this.safeNumber (balances, currencyId + '_locked'); if (used !== undefined) { used *= 1e-8; } - let total = this.safeFloat (balances, currencyId); + let total = this.safeNumber (balances, currencyId); if (total !== undefined) { total *= 1e-8; } @@ -70508,16 +68780,16 @@ module.exports = class foxbit extends Exchange { const timestamp = this.milliseconds (); const lowercaseQuote = market['quote'].toLowerCase (); const quoteVolume = 'vol_' + lowercaseQuote; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -70527,8 +68799,8 @@ module.exports = class foxbit extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -70541,14 +68813,11 @@ module.exports = class foxbit extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -70642,14 +68911,15 @@ module.exports = class foxbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],88:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],86:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending } = require ('./base/errors'); +const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending, ArgumentsRequired, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70888,6 +69158,7 @@ module.exports = class ftx extends Exchange { 'An unexpected error occurred': ExchangeNotAvailable, // {"error":"An unexpected error occurred, please try again later (58BC21C795).","success":false} 'Please retry request': ExchangeNotAvailable, // {"error":"Please retry request","success":false} 'Please try again': ExchangeNotAvailable, // {"error":"Please try again","success":false} + 'Only have permissions for subaccount': PermissionDenied, // {"success":false,"error":"Only have permissions for subaccount *sub_name*"} }, }, 'precisionMode': TICK_SIZE, @@ -71011,8 +69282,8 @@ module.exports = class ftx extends Exchange { // check if a market is a spot or future market const symbol = (type === 'future') ? this.safeString (market, 'name') : (base + '/' + quote); const active = this.safeValue (market, 'enabled'); - const sizeIncrement = this.safeFloat (market, 'sizeIncrement'); - const priceIncrement = this.safeFloat (market, 'priceIncrement'); + const sizeIncrement = this.safeNumber (market, 'sizeIncrement'); + const priceIncrement = this.safeNumber (market, 'priceIncrement'); const precision = { 'amount': sizeIncrement, 'price': priceIncrement, @@ -71090,28 +69361,28 @@ module.exports = class ftx extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); const timestamp = this.safeTimestamp (ticker, 'time', this.milliseconds ()); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'change24h'), + 'percentage': this.safeNumber (ticker, 'change24h'), 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24h'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24h'), 'info': ticker, }; } @@ -71151,14 +69422,6 @@ module.exports = class ftx extends Exchange { return this.parseTicker (result, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetMarkets (params); @@ -71237,11 +69500,11 @@ module.exports = class ftx extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -71362,6 +69625,45 @@ module.exports = class ftx extends Exchange { // "type": "otc" // } // + // with -ve fee + // { + // "id": 1171258927, + // "fee": -0.0000713875, + // "side": "sell", + // "size": 1, + // "time": "2021-03-11T13:34:35.523627+00:00", + // "type": "order", + // "price": 14.2775, + // "future": null, + // "market": "SOL/USD", + // "feeRate": -0.000005, + // "orderId": 33182929044, + // "tradeId": 582936801, + // "liquidity": "maker", + // "feeCurrency": "USD", + // "baseCurrency": "SOL", + // "quoteCurrency": "USD" + // } + // + // // from OTC order + // { + // "id": 1172129651, + // "fee": 0, + // "side": "sell", + // "size": 1.47568846, + // "time": "2021-03-11T15:04:46.893383+00:00", + // "type": "otc", + // "price": 14.60932598, + // "future": null, + // "market": null, + // "feeRate": 0, + // "orderId": null, + // "tradeId": null, + // "liquidity": "taker", + // "feeCurrency": "USD", + // "baseCurrency": "BCHA", + // "quoteCurrency": "USD" + // } const id = this.safeString (trade, 'id'); const takerOrMaker = this.safeString (trade, 'liquidity'); const marketId = this.safeString (trade, 'market'); @@ -71379,25 +69681,24 @@ module.exports = class ftx extends Exchange { } } const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } const orderId = this.safeString (trade, 'orderId'); @@ -71503,8 +69804,8 @@ module.exports = class ftx extends Exchange { const result = this.safeValue (response, 'result', {}); return { 'info': response, - 'maker': this.safeFloat (result, 'makerFee'), - 'taker': this.safeFloat (result, 'takerFee'), + 'maker': this.safeNumber (result, 'makerFee'), + 'taker': this.safeNumber (result, 'takerFee'), }; } @@ -71531,11 +69832,11 @@ module.exports = class ftx extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'coin')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -71658,9 +69959,9 @@ module.exports = class ftx extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); let status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filledSize'); - let remaining = this.safeFloat (order, 'remainingSize'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filledSize'); + let remaining = this.safeNumber (order, 'remainingSize'); if ((remaining === 0.0) && (amount !== undefined) && (filled !== undefined)) { remaining = Math.max (amount - filled, 0); if (remaining > 0) { @@ -71684,15 +69985,15 @@ module.exports = class ftx extends Exchange { } const side = this.safeString (order, 'side'); const type = this.safeString (order, 'type'); - const average = this.safeFloat (order, 'avgFillPrice'); - const price = this.safeFloat2 (order, 'price', 'triggerPrice', average); + const average = this.safeNumber (order, 'avgFillPrice'); + const price = this.safeNumber2 (order, 'price', 'triggerPrice', average); let cost = undefined; if (filled !== undefined && price !== undefined) { cost = filled * price; } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'triggeredAt')); const clientOrderId = this.safeString (order, 'clientId'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -71738,22 +70039,28 @@ module.exports = class ftx extends Exchange { request['clientId'] = clientOrderId; params = this.omit (params, [ 'clientId', 'clientOrderId' ]); } - let priceToPrecision = undefined; - if (price !== undefined) { - priceToPrecision = parseFloat (this.priceToPrecision (symbol, price)); - } - let method = 'privatePostConditionalOrders'; + let method = undefined; if (type === 'limit') { method = 'privatePostOrders'; - request['price'] = priceToPrecision; + request['price'] = parseFloat (this.priceToPrecision (symbol, price)); } else if (type === 'market') { method = 'privatePostOrders'; request['price'] = null; } else if ((type === 'stop') || (type === 'takeProfit')) { - request['triggerPrice'] = priceToPrecision; - // request['orderPrice'] = number; // optional, order type is limit if this is specified, otherwise market + method = 'privatePostConditionalOrders'; + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerPrice'); + if (stopPrice === undefined) { + throw new ArgumentsRequired (this.id + ' createOrder () requires a stopPrice parameter or a triggerPrice parameter for ' + type + ' orders'); + } else { + params = this.omit (params, [ 'stopPrice', 'triggerPrice' ]); + request['triggerPrice'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + } + if (price !== undefined) { + request['orderPrice'] = parseFloat (this.priceToPrecision (symbol, price)); // optional, order type is limit if this is specified, otherwise market + } } else if (type === 'trailingStop') { - request['trailValue'] = priceToPrecision; // negative for "sell", positive for "buy" + method = 'privatePostConditionalOrders'; + request['trailValue'] = parseFloat (this.priceToPrecision (symbol, price)); // negative for "sell", positive for "buy" } else { throw new InvalidOrder (this.id + ' createOrder () does not support order type ' + type + ', only limit, market, stop, trailingStop, or takeProfit orders are supported'); } @@ -71819,9 +70126,9 @@ module.exports = class ftx extends Exchange { const request = {}; let method = undefined; const clientOrderId = this.safeString2 (params, 'client_order_id', 'clientOrderId'); - const triggerPrice = this.safeFloat (params, 'triggerPrice'); - const orderPrice = this.safeFloat (params, 'orderPrice'); - const trailValue = this.safeFloat (params, 'trailValue'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); + const orderPrice = this.safeNumber (params, 'orderPrice'); + const trailValue = this.safeNumber (params, 'trailValue'); params = this.omit (params, [ 'client_order_id', 'clientOrderId', 'triggerPrice', 'orderPrice', 'trailValue' ]); const triggerPriceIsDefined = (triggerPrice !== undefined); const orderPriceIsDefined = (orderPrice !== undefined); @@ -72184,7 +70491,7 @@ module.exports = class ftx extends Exchange { return this.parseTransaction (result, currency); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetAccount (params); // @@ -72317,7 +70624,7 @@ module.exports = class ftx extends Exchange { // const code = this.safeCurrencyCode (this.safeString (transaction, 'coin')); const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'size'); + const amount = this.safeNumber (transaction, 'size'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const txid = this.safeString (transaction, 'txid'); @@ -72334,7 +70641,7 @@ module.exports = class ftx extends Exchange { address = notes.slice (12); } } - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -72469,13 +70776,14 @@ module.exports = class ftx extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],89:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],87:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, ArgumentsRequired, InvalidAddress, OrderNotFound, NotSupported, DDoSProtection, InsufficientFunds, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -72636,9 +70944,12 @@ module.exports = class gateio extends Exchange { }, }, 'commonCurrencies': { + '88MPH': 'MPH', + 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', + 'MPH': 'Morpher', // conflict with 88MPH 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', }, @@ -72685,9 +70996,9 @@ module.exports = class gateio extends Exchange { const currency = coin[id]; const code = this.safeCurrencyCode (id); const delisted = this.safeValue (currency, 'delisted', 0); - const withdrawDisabled = this.safeValue (currency, 'withdraw_disabled', 0); - const depositDisabled = this.safeValue (currency, 'deposit_disabled', 0); - const tradeDisabled = this.safeValue (currency, 'trade_disabled', 0); + const withdrawDisabled = this.safeInteger2 (currency, 'withdraw_disabled', 0); + const depositDisabled = this.safeInteger2 (currency, 'deposit_disabled', 0); + const tradeDisabled = this.safeInteger2 (currency, 'trade_disabled', 0); const listed = (delisted === 0); const withdrawEnabled = (withdrawDisabled === 0); const depositEnabled = (depositDisabled === 0); @@ -72776,7 +71087,7 @@ module.exports = class gateio extends Exchange { 'price': this.safeInteger (details, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (details, 'min_amount'), + 'min': this.safeNumber (details, 'min_amount'), 'max': undefined, }; const priceLimits = { @@ -72784,7 +71095,7 @@ module.exports = class gateio extends Exchange { 'max': undefined, }; const defaultCost = amountLimits['min'] * priceLimits['min']; - const minCost = this.safeFloat (this.options['limits']['cost']['min'], quote, defaultCost); + const minCost = this.safeNumber (this.options['limits']['cost']['min'], quote, defaultCost); const costLimits = { 'min': minCost, 'max': undefined, @@ -72794,10 +71105,10 @@ module.exports = class gateio extends Exchange { 'price': priceLimits, 'cost': costLimits, }; - const disabled = this.safeValue (details, 'trade_disabled'); + const disabled = this.safeInteger (details, 'trade_disabled'); const active = !disabled; const uppercaseId = id.toUpperCase (); - const fee = this.safeFloat (details, 'fee'); + const fee = this.safeNumber (details, 'fee'); result.push ({ 'id': id, 'uppercaseId': uppercaseId, @@ -72831,11 +71142,11 @@ module.exports = class gateio extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (available, currencyId); - account['used'] = this.safeFloat (locked, currencyId); + account['free'] = this.safeString (available, currencyId); + account['used'] = this.safeString (locked, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -72851,11 +71162,11 @@ module.exports = class gateio extends Exchange { // they return [ Timestamp, Volume, Close, High, Low, Open ] return [ this.safeInteger (ohlcv, 0), // t - this.safeFloat (ohlcv, 5), // o - this.safeFloat (ohlcv, 3), // h - this.safeFloat (ohlcv, 4), // l - this.safeFloat (ohlcv, 2), // c - this.safeFloat (ohlcv, 1), // v + this.safeNumber (ohlcv, 5), // o + this.safeNumber (ohlcv, 3), // h + this.safeNumber (ohlcv, 4), // l + this.safeNumber (ohlcv, 2), // c + this.safeNumber (ohlcv, 1), // v ]; } @@ -72867,11 +71178,11 @@ module.exports = class gateio extends Exchange { 'group_sec': this.timeframes[timeframe], }; // max limit = 1001 - if (limit !== undefined) { - const periodDurationInSeconds = this.parseTimeframe (timeframe); - const hours = parseInt ((periodDurationInSeconds * limit) / 3600); - request['range_hour'] = Math.max (0, hours - 1); - } + // if (limit !== undefined) { + // const periodDurationInSeconds = this.parseTimeframe (timeframe); + // const hours = parseInt ((periodDurationInSeconds * limit) / 3600); + // request['range_hour'] = Math.max (1, hours - 1); + // } const response = await this.publicGetCandlestick2Id (this.extend (request, params)); // // { @@ -72895,8 +71206,8 @@ module.exports = class gateio extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'percentChange'); let open = undefined; let change = undefined; let average = undefined; @@ -72906,17 +71217,17 @@ module.exports = class gateio extends Exchange { change = last - open; average = this.sum (last, open) / 2; } - open = this.safeFloat (ticker, 'open', open); - change = this.safeFloat (ticker, 'change', change); + open = this.safeNumber (ticker, 'open', open); + change = this.safeNumber (ticker, 'change', change); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high24hr', 'high'), - 'low': this.safeFloat2 (ticker, 'low24hr', 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber2 (ticker, 'high24hr', 'high'), + 'low': this.safeNumber2 (ticker, 'low24hr', 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -72926,8 +71237,8 @@ module.exports = class gateio extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), // gateio has them reversed - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), // gateio has them reversed + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -72973,27 +71284,24 @@ module.exports = class gateio extends Exchange { const id = this.safeString2 (trade, 'tradeID', 'id'); // take either of orderid or orderId const orderId = this.safeString2 (trade, 'orderid', 'orderNumber'); - const price = this.safeFloat2 (trade, 'rate', 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString2 (trade, 'rate', 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'role'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } let fee = undefined; let feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee_coin')); - let feeCost = this.safeFloat (trade, 'point_fee'); + let feeCost = this.safeNumber (trade, 'point_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'gt_fee'); + feeCost = this.safeNumber (trade, 'gt_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'fee'); + feeCost = this.safeNumber (trade, 'fee'); } else { feeCurrency = this.safeCurrencyCode ('GT'); } @@ -73137,23 +71445,20 @@ module.exports = class gateio extends Exchange { } else if (side === '2') { side = 'buy'; } - const price = this.safeFloat2 (order, 'initialRate', 'rate'); - const average = this.safeFloat (order, 'filledRate'); - const amount = this.safeFloat2 (order, 'initialAmount', 'amount'); - const filled = this.safeFloat (order, 'filledAmount'); + const price = this.safeNumber2 (order, 'initialRate', 'rate'); + const average = this.safeNumber (order, 'filledRate'); + const amount = this.safeNumber2 (order, 'initialAmount', 'amount'); + const filled = this.safeNumber (order, 'filledAmount'); // In the order status response, this field has a different name. - let remaining = this.safeFloat2 (order, 'leftAmount', 'left'); - if (remaining === undefined) { - remaining = amount - filled; - } - const feeCost = this.safeFloat (order, 'feeValue'); + const remaining = this.safeNumber2 (order, 'leftAmount', 'left'); + const feeCost = this.safeNumber (order, 'feeValue'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (order, 'feePercentage'); + let feeRate = this.safeNumber (order, 'feePercentage'); if (feeRate !== undefined) { feeRate = feeRate / 100; } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -73179,7 +71484,7 @@ module.exports = class gateio extends Exchange { 'rate': feeRate, }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -73370,7 +71675,7 @@ module.exports = class gateio extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'txid'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); if (address === 'false') { address = undefined; @@ -73378,7 +71683,7 @@ module.exports = class gateio extends Exchange { const timestamp = this.safeTimestamp (transaction, 'timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.parseTransactionType (id[0]); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -73467,7 +71772,7 @@ module.exports = class gateio extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],90:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],88:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -73475,6 +71780,7 @@ module.exports = class gateio extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidOrder, InvalidNonce, InsufficientFunds, AuthenticationError, PermissionDenied, NotSupported, OnMaintenance, RateLimitExceeded, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -73691,16 +71997,16 @@ module.exports = class gemini extends Exchange { // const base = this.safeCurrencyCode (baseId); const minAmountString = cells[1].replace ('', ''); const minAmountParts = minAmountString.split (' '); - const minAmount = this.safeFloat (minAmountParts, 0); + const minAmount = this.safeNumber (minAmountParts, 0); const amountPrecisionString = cells[2].replace ('', ''); const amountPrecisionParts = amountPrecisionString.split (' '); - const amountPrecision = this.safeFloat (amountPrecisionParts, 0); + const amountPrecision = this.safeNumber (amountPrecisionParts, 0); const idLength = marketId.length - 0; const quoteId = marketId.slice (idLength - 3, idLength); const quote = this.safeCurrencyCode (quoteId); const pricePrecisionString = cells[3].replace ('', ''); const pricePrecisionParts = pricePrecisionString.split (' '); - const pricePrecision = this.safeFloat (pricePrecisionParts, 0); + const pricePrecision = this.safeNumber (pricePrecisionParts, 0); const baseId = marketId.replace (quoteId, ''); const base = this.safeCurrencyCode (baseId); const symbol = base + '/' + quote; @@ -73928,11 +72234,11 @@ module.exports = class gemini extends Exchange { base = market['base']; quote = market['quote']; } - const price = this.safeFloat (ticker, 'price'); - const last = this.safeFloat2 (ticker, 'last', 'close', price); - let percentage = this.safeFloat (ticker, 'percentChange24h'); + const price = this.safeNumber (ticker, 'price'); + const last = this.safeNumber2 (ticker, 'last', 'close', price); + let percentage = this.safeNumber (ticker, 'percentChange24h'); let change = undefined; - let open = this.safeFloat (ticker, 'open'); + let open = this.safeNumber (ticker, 'open'); let average = undefined; if (last !== undefined) { if (open !== undefined) { @@ -73949,18 +72255,18 @@ module.exports = class gemini extends Exchange { average = this.sum (last, open) / 2; } } - const baseVolume = this.safeFloat (volume, baseId); - const quoteVolume = this.safeFloat (volume, quoteId); + const baseVolume = this.safeNumber (volume, baseId); + const quoteVolume = this.safeNumber (volume, quoteId); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -73976,14 +72282,6 @@ module.exports = class gemini extends Exchange { }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetV1Pricefeed (params); @@ -74024,17 +72322,14 @@ module.exports = class gemini extends Exchange { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); const fee = { - 'cost': this.safeFloat (trade, 'fee_amount'), + 'cost': this.safeNumber (trade, 'fee_amount'), 'currency': feeCurrencyCode, }; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeStringLower (trade, 'type'); const symbol = this.safeSymbol (undefined, market); @@ -74087,18 +72382,18 @@ module.exports = class gemini extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'timestampms'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const filled = this.safeFloat (order, 'executed_amount'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const filled = this.safeNumber (order, 'executed_amount'); let status = 'closed'; if (order['is_live']) { status = 'open'; @@ -74106,14 +72401,8 @@ module.exports = class gemini extends Exchange { if (order['is_cancelled']) { status = 'canceled'; } - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_execution_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_execution_price'); let type = this.safeString (order, 'type'); if (type === 'exchange limit') { type = 'limit'; @@ -74128,7 +72417,7 @@ module.exports = class gemini extends Exchange { const id = this.safeString (order, 'order_id'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'client_order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -74144,13 +72433,13 @@ module.exports = class gemini extends Exchange { 'price': price, 'stopPrice': undefined, 'average': average, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -74265,7 +72554,7 @@ module.exports = class gemini extends Exchange { status = 'ok'; } let fee = undefined; - const feeAmount = this.safeFloat (transaction, 'feeAmount'); + const feeAmount = this.safeNumber (transaction, 'feeAmount'); if (feeAmount !== undefined) { fee = { 'cost': feeAmount, @@ -74281,7 +72570,7 @@ module.exports = class gemini extends Exchange { 'address': address, 'tag': undefined, // or is it defined? 'type': type, // direction of the transaction, ('deposit' | 'withdraw') - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': undefined, @@ -74380,7 +72669,7 @@ module.exports = class gemini extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],91:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],89:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -74388,6 +72677,7 @@ module.exports = class gemini extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors'); const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -74601,8 +72891,8 @@ module.exports = class gopax extends Exchange { const minimums = this.safeValue (market, 'restApiOrderAmountMin', {}); const marketAsk = this.safeValue (minimums, 'marketAsk', {}); const marketBid = this.safeValue (minimums, 'marketBid', {}); - const takerFeePercent = this.safeFloat (market, 'takerFeePercent'); - const makerFeePercent = this.safeFloat (market, 'makerFeePercent'); + const takerFeePercent = this.safeNumber (market, 'takerFeePercent'); + const makerFeePercent = this.safeNumber (market, 'makerFeePercent'); const taker = parseFloat (this.decimalToPrecision (takerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); const maker = parseFloat (this.decimalToPrecision (makerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); result.push ({ @@ -74620,15 +72910,15 @@ module.exports = class gopax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (marketAsk, 'amount'), + 'min': this.safeNumber (marketAsk, 'amount'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'priceMin'), + 'min': this.safeNumber (market, 'priceMin'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (marketBid, 'amount'), + 'min': this.safeNumber (marketBid, 'amount'), 'max': undefined, }, }, @@ -74663,8 +72953,8 @@ module.exports = class gopax extends Exchange { const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'name'); - const fee = this.safeFloat (currency, 'withdrawalFee'); - const precision = this.safeFloat (currency, 'scale'); + const fee = this.safeNumber (currency, 'withdrawalFee'); + const precision = this.safeNumber (currency, 'scale'); result[code] = { 'id': id, 'info': currency, @@ -74687,7 +72977,7 @@ module.exports = class gopax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalAmountMin'), + 'min': this.safeNumber (currency, 'withdrawalAmountMin'), 'max': undefined, }, }, @@ -74755,8 +73045,8 @@ module.exports = class gopax extends Exchange { const marketId = this.safeString (ticker, 'name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (ticker, 'time')); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat2 (ticker, 'price', 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'price', 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -74767,20 +73057,20 @@ module.exports = class gopax extends Exchange { percentage = change / open * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidVolume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askVolume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidVolume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askVolume'), 'vwap': vwap, 'open': open, 'close': last, @@ -74816,14 +73106,6 @@ module.exports = class gopax extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTradingPairsStats (params); @@ -74845,8 +73127,8 @@ module.exports = class gopax extends Exchange { parsePublicTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let symbol = undefined; if ('symbol' in market) { symbol = this.safeString (market, 'symbol'); @@ -74872,14 +73154,14 @@ module.exports = class gopax extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const symbol = this.safeString (trade, 'tradingPairName').replace ('-', '/'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'baseAmount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'baseAmount'); let feeCurrency = symbol.slice (0, 3); if (side === 'sell') { feeCurrency = symbol.slice (4); } const fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': feeCurrency, 'rate': undefined, }; @@ -74961,15 +73243,15 @@ module.exports = class gopax extends Exchange { } else if (type === '2') { type = 'market'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'baseAmount'); - let cost = this.safeFloat (trade, 'quoteAmount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'baseAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteAmount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -75036,11 +73318,11 @@ module.exports = class gopax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -75080,14 +73362,14 @@ module.exports = class gopax extends Exchange { const balance = response[i]; const currencyId = this.safeString2 (balance, 'asset', 'isoAlpha3'); const code = this.safeCurrencyCode (currencyId); - const hold = this.safeFloat (balance, 'hold'); - const pendingWithdrawal = this.safeFloat (balance, 'pendingWithdrawal'); + const hold = this.safeString (balance, 'hold'); + const pendingWithdrawal = this.safeString (balance, 'pendingWithdrawal'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.sum (hold, pendingWithdrawal); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = Precise.stringAdd (hold, pendingWithdrawal); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -75164,42 +73446,36 @@ module.exports = class gopax extends Exchange { const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); const timeInForce = this.safeStringUpper (order, 'timeInForce'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - const remaining = this.safeFloat (order, 'remaining'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const stopPrice = this.safeNumber (order, 'stopPrice'); + const remaining = this.safeNumber (order, 'remaining'); const marketId = this.safeString (order, 'tradingPairName'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const balanceChange = this.safeValue (order, 'balanceChange', {}); - let filled = this.safeFloat (balanceChange, 'baseNet'); - let cost = this.safeFloat (balanceChange, 'quoteNet'); + const filled = this.safeNumber (balanceChange, 'baseNet'); + let cost = this.safeNumber (balanceChange, 'quoteNet'); if (cost !== undefined) { cost = Math.abs (cost); } let updated = undefined; - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } if ((filled !== undefined) && (filled > 0)) { updated = this.parse8601 (this.safeString (order, 'updatedAt')); } - if ((cost === undefined) && (price !== undefined) && (filled !== undefined)) { - cost = filled * price; - } let fee = undefined; if (side === 'buy') { const baseFee = this.safeValue (balanceChange, 'baseFee', {}); - const taking = this.safeFloat (baseFee, 'taking'); - const making = this.safeFloat (baseFee, 'making'); + const taking = this.safeNumber (baseFee, 'taking'); + const making = this.safeNumber (baseFee, 'making'); fee = { 'currency': market['base'], 'cost': this.sum (taking, making), }; } else { const quoteFee = this.safeValue (balanceChange, 'quoteFee', {}); - const taking = this.safeFloat (quoteFee, 'taking'); - const making = this.safeFloat (quoteFee, 'making'); + const taking = this.safeNumber (quoteFee, 'taking'); + const making = this.safeNumber (quoteFee, 'making'); fee = { 'currency': market['quote'], 'cost': this.sum (taking, making), @@ -75209,7 +73485,7 @@ module.exports = class gopax extends Exchange { if (timeInForce !== undefined) { postOnly = (timeInForce === 'PO'); } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'datetime': this.iso8601 (timestamp), @@ -75231,7 +73507,7 @@ module.exports = class gopax extends Exchange { 'trades': undefined, 'fee': fee, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -75379,7 +73655,7 @@ module.exports = class gopax extends Exchange { request['clientOrderId'] = clientOrderId; params = this.omit (params, 'clientOrderId'); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -75508,18 +73784,6 @@ module.exports = class gopax extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetCryptoDepositAddresses (params); @@ -75584,8 +73848,8 @@ module.exports = class gopax extends Exchange { } else if ((type === 'crypto_deposit' || type === 'fiat_deposit')) { type = 'deposit'; } - const amount = this.safeFloat (transaction, 'netAmount'); - const feeCost = this.safeFloat (transaction, 'feeAmount'); + const amount = this.safeNumber (transaction, 'netAmount'); + const feeCost = this.safeNumber (transaction, 'feeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -75729,7 +73993,7 @@ module.exports = class gopax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],92:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],90:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -75737,6 +74001,7 @@ module.exports = class gopax extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -76036,23 +74301,23 @@ module.exports = class hbtc extends Exchange { const filter = filters[j]; const filterType = this.safeString (filter, 'filterType'); if (filterType === 'LOT_SIZE') { - amountMin = this.safeFloat (filter, 'minQty'); - amountMax = this.safeFloat (filter, 'maxQty'); + amountMin = this.safeNumber (filter, 'minQty'); + amountMax = this.safeNumber (filter, 'maxQty'); } if (filterType === 'PRICE_FILTER') { - priceMin = this.safeFloat (filter, 'minPrice'); - priceMax = this.safeFloat (filter, 'maxPrice'); + priceMin = this.safeNumber (filter, 'minPrice'); + priceMax = this.safeNumber (filter, 'maxPrice'); } if (filterType === 'MIN_NOTIONAL') { - costMin = this.safeFloat (filter, 'minNotional'); + costMin = this.safeNumber (filter, 'minNotional'); } } if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) { costMin = amountMin * priceMin; } const precision = { - 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'), - 'amount': this.safeFloat (market, 'baseAssetPrecision'), + 'price': this.safeNumber2 (market, 'quotePrecision', 'quoteAssetPrecision'), + 'amount': this.safeNumber (market, 'baseAssetPrecision'), }; const limits = { 'amount': { @@ -76290,14 +74555,6 @@ module.exports = class hbtc extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidAsk (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -76449,8 +74706,8 @@ module.exports = class hbtc extends Exchange { const currencyId = this.safeString2 (balance, 'asset', 'tokenName'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -76460,12 +74717,12 @@ module.exports = class hbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = response[currencyId]; const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableMargin'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'availableMargin'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTrades (symbol, since = undefined, limit = 50, params = {}) { @@ -76506,11 +74763,11 @@ module.exports = class hbtc extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -77196,8 +75453,8 @@ module.exports = class hbtc extends Exchange { // const currencyId = this.safeString (item, 'tokenId'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'change'); - const after = this.safeFloat (item, 'total'); + const amount = this.safeNumber (item, 'change'); + const after = this.safeNumber (item, 'total'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -77337,8 +75594,8 @@ module.exports = class hbtc extends Exchange { } else { type = 'withdrawal'; } - const amount = this.safeFloat (transaction, 'quantity'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'quantity'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'feeTokenId'); @@ -77399,8 +75656,8 @@ module.exports = class hbtc extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'openPrice'); - const close = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; let average = undefined; @@ -77411,19 +75668,19 @@ module.exports = class hbtc extends Exchange { percentage = (change / open) * 100; } } - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber2 (ticker, 'bestBidPrice', 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber2 (ticker, 'bestAskPrice', 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': vwap, 'open': open, 'close': close, @@ -77473,17 +75730,14 @@ module.exports = class hbtc extends Exchange { // } // const id = this.safeString (trade, 'id'); - const timestamp = this.safeFloat (trade, 'time'); + const timestamp = this.safeNumber (trade, 'time'); const type = undefined; const orderId = this.safeString (trade, 'orderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let side = undefined; let takerOrMaker = undefined; if ('isBuyerMaker' in trade) { @@ -77497,7 +75751,7 @@ module.exports = class hbtc extends Exchange { side = isBuyer ? 'buy' : 'sell'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -77603,30 +75857,30 @@ module.exports = class hbtc extends Exchange { const symbol = this.safeSymbol (marketId, market); let type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'avgPrice'); + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'avgPrice'); let amount = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); + let cost = this.safeNumber (order, 'cummulativeQuoteQty'); let filled = undefined; let remaining = undefined; if (type === undefined) { type = this.safeStringLower (order, 'orderType'); if ((market !== undefined) && market['inverse']) { - cost = this.safeFloat (order, 'executedQty'); + cost = this.safeNumber (order, 'executedQty'); amount = undefined; } if (cost === 0.0) { filled = 0; } } else { - amount = this.safeFloat (order, 'origQty'); + amount = this.safeNumber (order, 'origQty'); if (type === 'market') { price = undefined; if (side === 'buy') { amount = undefined; } } - filled = this.safeFloat (order, 'executedQty'); + filled = this.safeNumber (order, 'executedQty'); if (filled !== undefined) { if (amount !== undefined) { remaining = amount - filled; @@ -77638,7 +75892,7 @@ module.exports = class hbtc extends Exchange { } const status = this.parseOrderStatus (this.safeString (order, 'status')); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const result = { 'info': order, 'id': id, @@ -77667,7 +75921,7 @@ module.exports = class hbtc extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'fee'); + const feeCost = this.safeNumber (fees[i], 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'feeToken'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -77740,7 +75994,7 @@ module.exports = class hbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],93:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],91:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -77748,6 +76002,7 @@ module.exports = class hbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, PermissionDenied, ExchangeError, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, RequestTimeout, AuthenticationError } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -77787,6 +76042,7 @@ module.exports = class hitbtc extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': 'M1', @@ -77824,10 +76080,10 @@ module.exports = class hitbtc extends Exchange { 'api': { 'public': { 'get': [ - 'symbol', // Available Currency Symbols - 'symbol/{symbol}', // Get symbol info 'currency', // Available Currencies 'currency/{currency}', // Get currency info + 'symbol', // Available Currency Symbols + 'symbol/{symbol}', // Get symbol info 'ticker', // Ticker list for all symbols 'ticker/{symbol}', // Ticker for symbol 'trades', @@ -77845,11 +76101,20 @@ module.exports = class hitbtc extends Exchange { 'order/{clientOrderId}', // Get a single order by clientOrderId 'trading/fee/all', // Get trading fee rate 'trading/fee/{symbol}', // Get trading fee rate + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', 'history/order', // Get historical orders 'history/trades', // Get historical trades 'history/order/{orderId}/trades', // Get historical trades by specified order 'account/balance', // Get main acccount balance - 'account/crypto/address/{currency}', // Get deposit crypro address + 'account/crypto/address/{currency}', // Get current address + 'account/crypto/addresses/{currency}', // Get last 10 deposit addresses for currency + 'account/crypto/used-addresses/{currency}', // Get last 10 unique addresses used for withdraw by currency + 'account/crypto/estimate-withdraw', 'account/crypto/is-mine/{address}', 'account/transactions', // Get account transactions 'account/transactions/{id}', // Get account transaction by id @@ -77860,23 +76125,33 @@ module.exports = class hitbtc extends Exchange { ], 'post': [ 'order', // Create new order - 'account/crypto/address/{currency}', // Create new deposit crypro address - 'account/crypto/withdraw', // Withdraw crypro + 'margin/order', + 'account/crypto/address/{currency}', // Create new crypto deposit address + 'account/crypto/withdraw', // Withdraw crypto 'account/crypto/transfer-convert', - 'account/transfer', // Transfer amount to trading + 'account/transfer', // Transfer amount to trading account or to main account + 'account/transfer/internal', 'sub-acc/freeze', 'sub-acc/activate', 'sub-acc/transfer', ], 'put': [ 'order/{clientOrderId}', // Create new order - 'account/crypto/withdraw/{id}', // Commit withdraw crypro + 'margin/account/{symbol}', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Commit crypto withdrawal 'sub-acc/acl/{subAccountUserId}', ], 'delete': [ 'order', // Cancel all open orders 'order/{clientOrderId}', // Cancel order - 'account/crypto/withdraw/{id}', // Rollback withdraw crypro + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Rollback crypto withdrawal ], // outdated? 'patch': [ @@ -77895,8 +76170,20 @@ module.exports = class hitbtc extends Exchange { }, 'options': { 'defaultTimeInForce': 'FOK', + 'accountsByType': { + 'bank': 'bank', + 'exchange': 'exchange', + 'main': 'bank', // alias of the above + 'trading': 'exchange', + }, + 'fetchBalanceMethod': { + 'account': 'account', + 'main': 'account', + 'trading': 'trading', + }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive 'BET': 'DAO.Casino', 'BOX': 'BOX Token', @@ -77923,7 +76210,6 @@ module.exports = class hitbtc extends Exchange { '20002': OrderNotFound, // canceling non-existent order '20001': InsufficientFunds, // {"error":{"code":20001,"message":"Insufficient funds","description":"Check that the funds are sufficient, given commissions"}} }, - 'orders': {}, // orders cache / emulation }); } @@ -77960,14 +76246,14 @@ module.exports = class hitbtc extends Exchange { if (id.indexOf ('_') >= 0) { symbol = id; } - const lot = this.safeFloat (market, 'quantityIncrement'); - const step = this.safeFloat (market, 'tickSize'); + const lot = this.safeNumber (market, 'quantityIncrement'); + const step = this.safeNumber (market, 'tickSize'); const precision = { 'price': step, 'amount': lot, }; - const taker = this.safeFloat (market, 'takeLiquidityRate'); - const maker = this.safeFloat (market, 'provideLiquidityRate'); + const taker = this.safeNumber (market, 'takeLiquidityRate'); + const maker = this.safeNumber (market, 'provideLiquidityRate'); const feeCurrencyId = this.safeString (market, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); result.push (this.extend (this.fees['trading'], { @@ -78002,6 +76288,49 @@ module.exports = class hitbtc extends Exchange { return result; } + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // account can be "exchange" or "bank", with aliases "main" or "trading" respectively + await this.loadMarkets (); + const currency = this.currency (code); + const requestAmount = this.currencyToPrecision (code, amount); + const request = { + 'currency': currency['id'], + 'amount': requestAmount, + }; + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + const keys = Object.keys (accountsByType); + if (fromId === undefined) { + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ') + ' instead of ' + fromId); + } + if (toId === undefined) { + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ') + ' instead of ' + toId); + } + if (fromId === toId) { + throw new ExchangeError (this.id + ' from and to cannot be the same account'); + } + type = fromId + 'To' + this.capitalize (toId); + } + request['type'] = type; + const response = await this.privatePostAccountTransfer (this.extend (request, params)); + // { id: '2db6ebab-fb26-4537-9ef8-1a689472d236' } + const id = this.safeString (response, 'id'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'amount': requestAmount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': undefined, + }; + } + async fetchCurrencies (params = {}) { const response = await this.publicGetCurrency (params); // @@ -78057,7 +76386,7 @@ module.exports = class hitbtc extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'payoutFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'payoutFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -78097,15 +76426,20 @@ module.exports = class hitbtc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } async fetchBalance (params = {}) { await this.loadMarkets (); const type = this.safeString (params, 'type', 'trading'); - const method = 'privateGet' + this.capitalize (type) + 'Balance'; + const fetchBalanceAccounts = this.safeValue (this.options, 'fetchBalanceMethod', {}); + const typeId = this.safeString (fetchBalanceAccounts, type); + if (typeId === undefined) { + throw new ExchangeError (this.id + ' fetchBalance account type must be either main or trading'); + } + const method = 'privateGet' + this.capitalize (typeId) + 'Balance'; const query = this.omit (params, 'type'); const response = await this[method] (query); const result = { 'info': response }; @@ -78114,11 +76448,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -78135,11 +76469,11 @@ module.exports = class hitbtc extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'max'), - this.safeFloat (ohlcv, 'min'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'max'), + this.safeNumber (ohlcv, 'min'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -78185,10 +76519,10 @@ module.exports = class hitbtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); let change = undefined; let percentage = undefined; let average = undefined; @@ -78204,11 +76538,11 @@ module.exports = class hitbtc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -78284,7 +76618,7 @@ module.exports = class hitbtc extends Exchange { market = this.safeMarket (marketId, market); const symbol = market['symbol']; let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = market ? market['feeCurrency'] : undefined; fee = { @@ -78296,9 +76630,11 @@ module.exports = class hitbtc extends Exchange { // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const orderId = this.safeString (trade, 'clientOrderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); const id = this.safeString (trade, 'id'); return { @@ -78397,11 +76733,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'hash'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -78589,66 +76925,25 @@ module.exports = class hitbtc extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'cumQuantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'cumQuantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); // we use clientOrderId as the order id with this exchange intentionally // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const id = this.safeString (order, 'clientOrderId'); const clientOrderId = id; - let price = this.safeFloat (order, 'price'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - if (price !== undefined) { - cost = filled * price; - } - } - } + const price = this.safeNumber (order, 'price'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); let trades = this.safeValue (order, 'tradesReport'); - let fee = undefined; - let average = this.safeValue (order, 'avgPrice'); + const fee = undefined; + const average = this.safeNumber (order, 'avgPrice'); if (trades !== undefined) { trades = this.parseTrades (trades, market); - let feeCost = undefined; - const numTrades = trades.length; - let tradesCost = 0; - for (let i = 0; i < numTrades; i++) { - if (feeCost === undefined) { - feeCost = 0; - } - tradesCost = this.sum (tradesCost, trades[i]['cost']); - const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); - if (tradeFeeCost !== undefined) { - feeCost = this.sum (feeCost, tradeFeeCost); - } - } - cost = tradesCost; - if ((filled !== undefined) && (filled > 0)) { - if (average === undefined) { - average = cost / filled; - } - if (type === 'market') { - if (price === undefined) { - price = average; - } - } - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, // https://github.com/ccxt/ccxt/issues/5674 'timestamp': created, @@ -78663,13 +76958,13 @@ module.exports = class hitbtc extends Exchange { 'stopPrice': undefined, 'average': average, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -78930,7 +77225,7 @@ module.exports = class hitbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],94:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],92:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -78938,6 +77233,7 @@ module.exports = class hitbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { BadRequest, AuthenticationError, NetworkError, ArgumentsRequired, OrderNotFound, InsufficientFunds } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -78948,7 +77244,7 @@ module.exports = class hollaex extends Exchange { 'name': 'HollaEx', 'countries': [ 'KR' ], 'rateLimit': 333, - 'version': 'v1', + 'version': 'v2', 'has': { 'CORS': false, 'fetchMarkets': true, @@ -78968,13 +77264,13 @@ module.exports = class hollaex extends Exchange { 'cancelOrder': true, 'cancelAllOrders': true, 'fetchOpenOrders': true, - 'fetchClosedOrders': false, + 'fetchClosedOrders': true, 'fetchOpenOrder': true, 'fetchOrder': false, 'fetchDeposits': true, 'fetchWithdrawals': true, 'fetchTransactions': false, - 'fetchOrders': false, + 'fetchOrders': true, 'fetchMyTrades': true, 'withdraw': true, 'fetchDepositAddress': true, @@ -78999,13 +77295,17 @@ module.exports = class hollaex extends Exchange { 'public': { 'get': [ 'health', - 'constant', + 'constants', + 'kit', + 'tiers', 'ticker', - 'ticker/all', + 'tickers', + 'orderbook', 'orderbooks', 'trades', 'chart', - // TradingView data + 'charts', + // TradingView 'udf/config', 'udf/history', 'udf/symbols', @@ -79015,20 +77315,20 @@ module.exports = class hollaex extends Exchange { 'get': [ 'user', 'user/balance', - 'user/trades', - 'user/orders', - 'user/orders/{order_id}', 'user/deposits', 'user/withdrawals', - 'user/withdraw/{currency}/fee', + 'user/withdrawal/fee', + 'user/trades', + 'orders', + 'orders/{order_id}', ], 'post': [ 'user/request-withdrawal', 'order', ], 'delete': [ - 'user/orders', - 'user/orders/{order_id}', + 'order/all', + 'order', ], }, }, @@ -79063,7 +77363,7 @@ module.exports = class hollaex extends Exchange { } async fetchMarkets (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); // // { // coins: { @@ -79130,17 +77430,17 @@ module.exports = class hollaex extends Exchange { 'quoteId': quoteId, 'active': active, 'precision': { - 'price': this.safeFloat (market, 'increment_price'), - 'amount': this.safeFloat (market, 'increment_size'), + 'price': this.safeNumber (market, 'increment_price'), + 'amount': this.safeNumber (market, 'increment_size'), }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, 'max': undefined }, }, @@ -79151,7 +77451,7 @@ module.exports = class hollaex extends Exchange { } async fetchCurrencies (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); const coins = this.safeValue (response, 'coins', {}); const keys = Object.keys (coins); const result = {}; @@ -79163,8 +77463,8 @@ module.exports = class hollaex extends Exchange { const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'fullname'); const active = this.safeValue (currency, 'active'); - const fee = this.safeFloat (currency, 'withdrawal_fee'); - const precision = this.safeFloat (currency, 'increment_unit'); + const fee = this.safeNumber (currency, 'withdrawal_fee'); + const precision = this.safeNumber (currency, 'increment_unit'); const withdrawalLimits = this.safeValue (currency, 'withdrawal_limits', []); result[code] = { 'id': id, @@ -79177,8 +77477,8 @@ module.exports = class hollaex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min'), - 'max': this.safeFloat (currency, 'max'), + 'min': this.safeNumber (currency, 'min'), + 'max': this.safeNumber (currency, 'max'), }, 'price': { 'min': undefined, @@ -79267,7 +77567,7 @@ module.exports = class hollaex extends Exchange { async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.publicGetTickerAll (this.extend (params)); + const response = await this.publicGetTickers (this.extend (params)); // // { // "bch-usdt": { @@ -79330,27 +77630,27 @@ module.exports = class hollaex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString2 (ticker, 'time', 'timestamp')); - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const result = { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, - 'last': this.safeFloat (ticker, 'last', close), + 'last': this.safeNumber (ticker, 'last', close), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, }; return result; @@ -79408,15 +77708,12 @@ module.exports = class hollaex extends Exchange { const datetime = this.safeString (trade, 'timestamp'); const timestamp = this.parse8601 (datetime); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const quote = market['quote']; @@ -79501,11 +77798,11 @@ module.exports = class hollaex extends Exchange { // return [ this.parse8601 (this.safeString (response, 'time')), - this.safeFloat (response, 'open'), - this.safeFloat (response, 'high'), - this.safeFloat (response, 'low'), - this.safeFloat (response, 'close'), - this.safeFloat (response, 'volume'), + this.safeNumber (response, 'open'), + this.safeNumber (response, 'high'), + this.safeNumber (response, 'low'), + this.safeNumber (response, 'close'), + this.safeNumber (response, 'volume'), ]; } @@ -79530,11 +77827,11 @@ module.exports = class hollaex extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (response, currencyId + '_available'); - account['total'] = this.safeFloat (response, currencyId + '_balance'); + account['free'] = this.safeString (response, currencyId + '_available'); + account['total'] = this.safeString (response, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrder (id, symbol = undefined, params = {}) { @@ -79542,67 +77839,146 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateGetUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateGetOrdersOrderId (this.extend (request, params)); // // { - // "created_at": "2018-03-23T04:14:08.663Z", - // "title": "string", - // "side": "sell", - // "type": "limit", - // "price": 0, - // "size": 0, - // "symbol": "xht-usdt", // "id": "string", - // "created_by": 1, - // "filled": 0 + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } // } // return this.parseOrder (response); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'open': true, + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'status': 'filled', + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = undefined; - const request = {}; + const request = { + // 'symbol': market['id'], + // 'side': 'buy', // 'sell' + // 'status': 'new', // 'filled', 'pfilled', 'canceled' + // 'open': true, + // 'limit': limit, // default 50, max 100 + // 'page': 1, + // 'order_by': 'created_at', // id, ... + // 'order': 'asc', // 'desc' + // 'start_date': this.iso8601 (since), + // 'end_date': this.iso8601 (this.milliseconds ()), + }; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } - const response = await this.privateGetUserOrders (this.extend (request, params)); + if (since !== undefined) { + request['start_date'] = this.iso8601 (since); + } + if (limit !== undefined) { + request['limit'] = limit; // default 50, max 100 + } + const response = await this.privateGetOrders (this.extend (request, params)); // - // [ - // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 - // } - // ] + // { + // "count": 1, + // "data": [ + // { + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } + // } + // ] + // } // - return this.parseOrders (response, market); + const data = this.safeValue (response, 'data', []); + return this.parseOrders (data, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'new': 'open', + 'pfilled': 'open', + 'filled': 'closed', + 'canceled': 'canceled', + }; + return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // - // fetchOpenOrder, fetchOpenOrders + // createOrder, fetchOpenOrder, fetchOpenOrders // // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // }, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, // } // const marketId = this.safeString (order, 'symbol'); @@ -79611,21 +77987,11 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filled'); - let cost = undefined; - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = filled * price; - } - } - const status = (type === 'market') ? 'closed' : 'open'; - const result = { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filled'); + const status = this.parseOrderStatus (this.safeString (order, 'status')); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -79641,40 +78007,56 @@ module.exports = class hollaex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; - return result; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); - const order = { + const request = { 'symbol': market['id'], 'side': side, 'size': amount, 'type': type, + // 'stop': parseFloat (this.priceToPrecision (symbol, stopPrice)), + // 'meta': {}, // other options such as post_only }; if (type !== 'market') { - order['price'] = price; + request['price'] = price; } - const response = await this.privatePostOrder (this.extend (order, params)); + const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop'); + if (stopPrice !== undefined) { + request['stop'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + params = this.omit (params, [ 'stopPrice', 'stop' ]); + } + const response = await this.privatePostOrder (this.extend (request, params)); // // { + // "fee": 0, + // "meta": {}, // "symbol": "xht-usdt", // "side": "sell", - // "size": 1, + // "size": 0.1, // "type": "limit", - // "price": 0.1, + // "price": 1, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, + // "fee_coin": "usdt", // "id": "string", - // "created_by": 34, + // "created_by": 116, // "filled": 0, - // "status": "pending" + // "status": "new", + // "updated_at": "2021-02-17T03:03:19.231Z", + // "created_at": "2021-02-17T03:03:19.231Z", + // "stop": null // } // return this.parseOrder (response, market); @@ -79685,7 +78067,7 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateDeleteUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateDeleteOrder (this.extend (request, params)); // // { // "title": "string", @@ -79710,7 +78092,7 @@ module.exports = class hollaex extends Exchange { market = this.markets (symbol); request['symbol'] = market['id']; } - const response = await this.privateDeleteUserOrders (this.extend (request, params)); + const response = await this.privateDeleteOrderAll (this.extend (request, params)); // // [ // { @@ -79976,7 +78358,7 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_at')); const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const type = this.safeString (transaction, 'type'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); let addressTo = undefined; const addressFrom = undefined; @@ -80006,7 +78388,7 @@ module.exports = class hollaex extends Exchange { } const fee = { 'currency': code, - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), }; return { 'info': transaction, @@ -80105,7 +78487,7 @@ module.exports = class hollaex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],95:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],93:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -80146,7 +78528,7 @@ module.exports = class huobijp extends huobipro { } }; -},{"./base/errors":8,"./huobipro.js":96}],96:[function(require,module,exports){ +},{"./base/errors":9,"./huobipro.js":94}],94:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -80154,6 +78536,7 @@ module.exports = class huobijp extends huobipro { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, ExchangeNotAvailable, OnMaintenance, InvalidOrder, OrderNotFound, InsufficientFunds, ArgumentsRequired, BadSymbol, BadRequest, RequestTimeout, NetworkError } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -80171,7 +78554,9 @@ module.exports = class huobipro extends Exchange { 'hostname': 'api.huobi.pro', // api.testnet.huobi.pro 'pro': true, 'has': { + 'cancelAllOrders': true, 'cancelOrder': true, + 'cancelOrders': true, 'CORS': false, 'createOrder': true, 'fetchBalance': true, @@ -80338,6 +78723,7 @@ module.exports = class huobipro extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.002, @@ -80401,6 +78787,7 @@ module.exports = class huobipro extends Exchange { // https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/ 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', + 'BIFI': 'Bitcoin File', // conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706 }, }); } @@ -80465,8 +78852,8 @@ module.exports = class huobipro extends Exchange { 'info': limits, 'limits': { 'amount': { - 'min': this.safeFloat (limits, 'limit-order-must-greater-than'), - 'max': this.safeFloat (limits, 'limit-order-must-less-than'), + 'min': this.safeNumber (limits, 'limit-order-must-greater-than'), + 'max': this.safeNumber (limits, 'limit-order-must-less-than'), }, }, }; @@ -80500,9 +78887,9 @@ module.exports = class huobipro extends Exchange { }; const maker = (base === 'OMG') ? 0 : 0.2 / 100; const taker = (base === 'OMG') ? 0 : 0.2 / 100; - const minAmount = this.safeFloat (market, 'min-order-amt', Math.pow (10, -precision['amount'])); - const maxAmount = this.safeFloat (market, 'max-order-amt'); - const minCost = this.safeFloat (market, 'min-order-value', 0); + const minAmount = this.safeNumber (market, 'min-order-amt', Math.pow (10, -precision['amount'])); + const maxAmount = this.safeNumber (market, 'max-order-amt'); + const minCost = this.safeNumber (market, 'min-order-value', 0); const state = this.safeString (market, 'state'); const active = (state === 'online'); result.push ({ @@ -80581,24 +78968,24 @@ module.exports = class huobipro extends Exchange { let askVolume = undefined; if ('bid' in ticker) { if (Array.isArray (ticker['bid'])) { - bid = this.safeFloat (ticker['bid'], 0); - bidVolume = this.safeFloat (ticker['bid'], 1); + bid = this.safeNumber (ticker['bid'], 0); + bidVolume = this.safeNumber (ticker['bid'], 1); } else { - bid = this.safeFloat (ticker, 'bid'); + bid = this.safeNumber (ticker, 'bid'); bidVolume = this.safeValue (ticker, 'bidSize'); } } if ('ask' in ticker) { if (Array.isArray (ticker['ask'])) { - ask = this.safeFloat (ticker['ask'], 0); - askVolume = this.safeFloat (ticker['ask'], 1); + ask = this.safeNumber (ticker['ask'], 0); + askVolume = this.safeNumber (ticker['ask'], 1); } else { - ask = this.safeFloat (ticker, 'ask'); + ask = this.safeNumber (ticker, 'ask'); askVolume = this.safeValue (ticker, 'askSize'); } } - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -80609,15 +78996,15 @@ module.exports = class huobipro extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -80706,7 +79093,7 @@ module.exports = class huobipro extends Exchange { // } // const ticker = this.parseTicker (response['tick'], market); - const timestamp = this.safeValue (response, 'ts'); + const timestamp = this.safeInteger (response, 'ts'); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); return ticker; @@ -80775,21 +79162,18 @@ module.exports = class huobipro extends Exchange { type = typeParts[1]; } const takerOrMaker = this.safeString (trade, 'role'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'filled-amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'filled-amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - let feeCost = this.safeFloat (trade, 'filled-fees'); + let feeCost = this.safeNumber (trade, 'filled-fees'); let feeCurrency = undefined; if (market !== undefined) { feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-currency')); } - const filledPoints = this.safeFloat (trade, 'filled-points'); + const filledPoints = this.safeNumber (trade, 'filled-points'); if (filledPoints !== undefined) { if ((feeCost === undefined) || (feeCost === 0.0)) { feeCost = filledPoints; @@ -80903,11 +79287,11 @@ module.exports = class huobipro extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -81004,11 +79388,11 @@ module.exports = class huobipro extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'deposit-min-amount'), + 'min': this.safeNumber (currency, 'deposit-min-amount'), 'max': Math.pow (10, precision), }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw-min-amount'), + 'min': this.safeNumber (currency, 'withdraw-min-amount'), 'max': Math.pow (10, precision), }, }, @@ -81039,14 +79423,14 @@ module.exports = class huobipro extends Exchange { account = this.account (); } if (balance['type'] === 'trade') { - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); } if (balance['type'] === 'frozen') { - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrdersByStates (states, symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -81221,28 +79605,14 @@ module.exports = class huobipro extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (order, 'created-at'); - let amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount - if ((type === 'market') && (side === 'buy')) { - amount = (status === 'closed') ? filled : undefined; - } - let price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - const cost = this.safeFloat2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - // if cost is defined and filled is not zero - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - const feeCost = this.safeFloat2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees + const cost = this.safeNumber2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo + const feeCost = this.safeNumber2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -81254,7 +79624,7 @@ module.exports = class huobipro extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -81268,15 +79638,15 @@ module.exports = class huobipro extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -81350,26 +79720,82 @@ module.exports = class huobipro extends Exchange { }); } - currencyToPrecision (currency, fee) { - return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); + async cancelOrders (ids, symbol = undefined, params = {}) { + await this.loadMarkets (); + const clientOrderIds = this.safeValue2 (params, 'clientOrderIds', 'client-order-ids'); + params = this.omit (params, [ 'clientOrderIds', 'client-order-ids' ]); + const request = {}; + if (clientOrderIds === undefined) { + request['order-ids'] = ids; + } else { + request['client-order-ids'] = clientOrderIds; + } + const response = await this.privatePostOrderOrdersBatchcancel (this.extend (request, params)); + // + // { + // "status": "ok", + // "data": { + // "success": [ + // "5983466" + // ], + // "failed": [ + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "first" + // }, + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "second" + // }, + // { + // "err-msg": "The record is not found.", + // "order-id": "", + // "err-code": "base-not-found", + // "client-order-id": "third" + // } + // ] + // } + // } + // + return response; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (market[key], cost)), + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'account-id' string false NA The account id used for this cancel Refer to GET /v1/account/accounts + // 'symbol': market['id'], // a list of comma-separated symbols, all symbols by default + // 'types' 'string', buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok + // 'side': 'buy', // or 'sell' + // 'size': 100, // the number of orders to cancel 1-100 }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.privatePostOrderOrdersBatchCancelOpenOrders (this.extend (request, params)); + // + // { + // code: 200, + // data: { + // "success-count": 2, + // "failed-count": 0, + // "next-id": 5454600 + // } + // } + // + return response; + } + + currencyToPrecision (currency, fee) { + return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); } parseDepositAddress (depositAddress, currency = undefined) { @@ -81511,7 +79937,7 @@ module.exports = class huobipro extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const tag = this.safeString (transaction, 'address-tag'); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -81524,7 +79950,7 @@ module.exports = class huobipro extends Exchange { 'address': this.safeString (transaction, 'address'), 'tag': tag, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -81654,504 +80080,7 @@ module.exports = class huobipro extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],97:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class ice3x extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'ice3x', - 'name': 'ICE3X', - 'countries': [ 'ZA' ], // South Africa - 'rateLimit': 1000, - 'version': 'v1', - 'has': { - 'cancelOrder': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchCurrencies': true, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTrades': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg', - 'api': 'https://ice3x.com/api', - 'www': 'https://ice3x.com', // 'https://ice3x.co.za', - 'doc': 'https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017', - 'fees': [ - 'https://help.ice3.com/support/solutions/articles/11000033293-trading-fees', - 'https://help.ice3.com/support/solutions/articles/11000033288-fees-explained', - 'https://help.ice3.com/support/solutions/articles/11000008131-what-are-your-fiat-deposit-and-withdrawal-fees-', - 'https://help.ice3.com/support/solutions/articles/11000033289-deposit-fees', - ], - 'referral': 'https://ice3x.com?ref=14341802', - }, - 'api': { - 'public': { - 'get': [ - 'currency/list', - 'currency/info', - 'pair/list', - 'pair/info', - 'stats/marketdepthfull', - 'stats/marketdepthbtcav', - 'stats/marketdepth', - 'orderbook/info', - 'trade/list', - 'trade/info', - ], - }, - 'private': { - 'post': [ - 'balance/list', - 'balance/info', - 'order/new', - 'order/cancel', - 'order/list', - 'order/info', - 'trade/list', - 'trade/info', - 'transaction/list', - 'transaction/info', - 'invoice/list', - 'invoice/info', - 'invoice/pdf', - ], - }, - }, - 'fees': { - 'trading': { - 'maker': 0.005, - 'taker': 0.005, - }, - }, - 'precision': { - 'amount': 8, - 'price': 8, - }, - }); - } - - async fetchCurrencies (params = {}) { - const response = await this.publicGetCurrencyList (params); - const currencies = response['response']['entities']; - const precision = this.precision['amount']; - const result = {}; - for (let i = 0; i < currencies.length; i++) { - const currency = currencies[i]; - const id = this.safeString (currency, 'currency_id'); - const currencyId = this.safeString (currency, 'iso'); - const code = this.safeCurrencyCode (currencyId); - result[code] = { - 'id': id, - 'code': code, - 'name': currency['name'], - 'active': true, - 'precision': precision, - 'limits': { - 'amount': { - 'min': undefined, - 'max': Math.pow (10, precision), - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': Math.pow (10, precision), - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - }, - 'info': currency, - 'fee': undefined, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - if (this.currencies_by_id === undefined) { - this.currencies = await this.fetchCurrencies (); - this.currencies_by_id = this.indexBy (this.currencies, 'id'); - } - const response = await this.publicGetPairList (params); - const markets = this.safeValue (response['response'], 'entities'); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = this.safeString (market, 'pair_id'); - const baseId = this.safeString (market, 'currency_id_from'); - const quoteId = this.safeString (market, 'currency_id_to'); - const baseCurrency = this.currencies_by_id[baseId]; - const quoteCurrency = this.currencies_by_id[quoteId]; - const base = baseCurrency['code']; - const quote = quoteCurrency['code']; - const symbol = base + '/' + quote; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': undefined, - 'info': market, - 'precision': this.precision, - 'limits': this.limits, - }); - } - return result; - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.milliseconds (); - const symbol = market['symbol']; - const last = this.safeFloat (ticker, 'last_price'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'max_bid'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'min_ask'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'vol'), - 'info': ticker, - }; - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetStatsMarketdepthfull (this.extend (request, params)); - const ticker = this.safeValue (response['response'], 'entity'); - return this.parseTicker (ticker, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetStatsMarketdepthfull (params); - const tickers = this.safeValue (response['response'], 'entities'); - const result = {}; - for (let i = 0; i < tickers.length; i++) { - const ticker = tickers[i]; - const marketId = this.safeString (ticker, 'pair_id'); - const market = this.safeValue (this.marketsById, marketId); - if (market !== undefined) { - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); - } - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'pair_id': this.marketId (symbol), - }; - if (limit !== undefined) { - const type = this.safeString (params, 'type'); - if ((type !== 'ask') && (type !== 'bid')) { - // eslint-disable-next-line quotes - throw new ArgumentsRequired (this.id + " fetchOrderBook() requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit"); - } else { - request['items_per_page'] = limit; - } - } - const response = await this.publicGetOrderbookInfo (this.extend (request, params)); - const orderbook = this.safeValue (response['response'], 'entities'); - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.safeTimestamp (trade, 'created'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } - const type = 'limit'; - const side = this.safeString (trade, 'type'); - const id = this.safeString (trade, 'trade_id'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'id': id, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': type, - 'side': side, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetTradeList (this.extend (request, params)); - const trades = this.safeValue (response['response'], 'entities'); - return this.parseTrades (trades, market, since, limit); - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostBalanceList (params); - const result = { 'info': response }; - const balances = this.safeValue (response['response'], 'entities', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - // currency ids are numeric strings - const currencyId = this.safeString (balance, 'currency_id'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseOrder (order, market = undefined) { - const pairId = this.safeInteger (order, 'pair_id'); - let symbol = undefined; - if (pairId && !market && (pairId in this.marketsById)) { - market = this.marketsById[pairId]; - symbol = market['symbol']; - } - const timestamp = this.safeTimestamp (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - let status = this.safeInteger (order, 'active'); - let remaining = this.safeFloat (order, 'remaining'); - let filled = undefined; - if (status === 1) { - status = 'open'; - } else { - status = 'closed'; - remaining = 0; - filled = amount; - } - let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - }; - if (market !== undefined) { - fee['currency'] = market['quote']; - } - } - return { - 'id': this.safeString (order, 'order_id'), - 'clientOrderId': undefined, - 'datetime': this.iso8601 (timestamp), - 'timestamp': timestamp, - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': 'limit', - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': this.safeString (order, 'type'), - 'price': price, - 'stopPrice': undefined, - 'cost': undefined, - 'amount': amount, - 'filled': filled, - 'remaining': remaining, - 'trades': undefined, - 'fee': fee, - 'info': order, - 'average': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - 'type': side, - 'amount': amount, - 'price': price, - }; - const response = await this.privatePostOrderNew (this.extend (request, params)); - const order = this.parseOrder ({ - 'order_id': response['response']['entity']['order_id'], - 'created': this.seconds (), - 'active': 1, - 'type': side, - 'price': price, - 'volume': amount, - 'remaining': amount, - 'info': response, - }, market); - return order; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - const request = { - 'order_id': id, - }; - return await this.privatePostOrderCancel (this.extend (request, params)); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'order _id': id, - }; - const response = await this.privatePostOrderInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const order = this.safeValue (data, 'entity'); - return this.parseOrder (order); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.privatePostOrderList (params); - const data = this.safeValue (response, 'response', {}); - const orders = this.safeValue (data, 'entities', []); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - return this.parseOrders (orders, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - if (limit !== undefined) { - request['items_per_page'] = limit; - } - if (since !== undefined) { - request['date_from'] = parseInt (since / 1000); - } - const response = await this.privatePostTradeList (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const trades = this.safeValue (data, 'entities', []); - return this.parseTrades (trades, market, since, limit); - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency_id': currency['id'], - }; - const response = await this.privatePostBalanceInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const balance = this.safeValue (data, 'entity', {}); - const address = this.safeString (balance, 'address'); - const status = address ? 'ok' : 'none'; - return { - 'currency': code, - 'address': address, - 'tag': undefined, - 'status': status, - 'info': response, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/' + this.version + '/' + path; - if (api === 'public') { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } - } else { - this.checkRequiredCredentials (); - body = this.urlencode (this.extend ({ - 'nonce': this.nonce (), - }, params)); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const response = await this.fetch2 (path, api, method, params, headers, body); - const errors = this.safeValue (response, 'errors'); - const data = this.safeValue (response, 'response'); - if (errors || !data) { - const authErrorKeys = [ 'Key', 'user_id', 'Sign' ]; - for (let i = 0; i < authErrorKeys.length; i++) { - const errorKey = authErrorKeys[i]; - const errorMessage = this.safeString (errors, errorKey); - if (!errorMessage) { - continue; - } - if (errorKey === 'user_id' && errorMessage.indexOf ('authorization') < 0) { - continue; - } - throw new AuthenticationError (errorMessage); - } - throw new ExchangeError (this.json (errors)); - } - return response; - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],98:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],95:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -82159,6 +80088,7 @@ module.exports = class ice3x extends Exchange { const Exchange = require ('./base/Exchange'); const { PAD_WITH_ZERO } = require ('./base/functions/number'); const { InvalidOrder, InsufficientFunds, ExchangeError, ExchangeNotAvailable, DDoSProtection, BadRequest, NotSupported, InvalidAddress, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -82395,14 +80325,6 @@ module.exports = class idex extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // { // market: 'DIL-ETH', @@ -82422,16 +80344,16 @@ module.exports = class idex extends Exchange { // } const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'baseVolume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'baseVolume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'open'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const close = this.safeFloat (ticker, 'close'); - const ask = this.safeFloat (ticker, 'ask'); - const bid = this.safeFloat (ticker, 'bid'); - let percentage = this.safeFloat (ticker, 'percentChange'); + const open = this.safeNumber (ticker, 'open'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const close = this.safeNumber (ticker, 'close'); + const ask = this.safeNumber (ticker, 'ask'); + const bid = this.safeNumber (ticker, 'bid'); + let percentage = this.safeNumber (ticker, 'percentChange'); if (percentage !== undefined) { percentage = 1 + percentage / 100; } @@ -82507,11 +80429,11 @@ module.exports = class idex extends Exchange { // sequence: 3853 // } const timestamp = this.safeInteger (ohlcv, 'start'); - const open = this.safeFloat (ohlcv, 'open'); - const high = this.safeFloat (ohlcv, 'high'); - const low = this.safeFloat (ohlcv, 'low'); - const close = this.safeFloat (ohlcv, 'close'); - const volume = this.safeFloat (ohlcv, 'volume'); + const open = this.safeNumber (ohlcv, 'open'); + const high = this.safeNumber (ohlcv, 'high'); + const low = this.safeNumber (ohlcv, 'low'); + const close = this.safeNumber (ohlcv, 'close'); + const volume = this.safeNumber (ohlcv, 'volume'); return [ timestamp, open, high, low, close, volume ]; } @@ -82573,9 +80495,14 @@ module.exports = class idex extends Exchange { // txStatus: 'mined' // } const id = this.safeString (trade, 'fillId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'quoteQuantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteQuantity'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const timestamp = this.safeInteger (trade, 'time'); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); @@ -82584,7 +80511,7 @@ module.exports = class idex extends Exchange { const oppositeSide = (makerSide === 'buy') ? 'sell' : 'buy'; const side = this.safeString (trade, 'side', oppositeSide); const takerOrMaker = this.safeString (trade, 'liquidity', 'taker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); @@ -82657,8 +80584,8 @@ module.exports = class idex extends Exchange { const result = []; for (let i = 0; i < bookSide.length; i++) { const order = bookSide[i]; - const price = this.safeFloat (order, 0); - const amount = this.safeFloat (order, 1); + const price = this.safeNumber (order, 0); + const amount = this.safeNumber (order, 1); const orderCount = this.safeInteger (order, 2); result.push ([ price, amount, orderCount ]); } @@ -82745,16 +80672,13 @@ module.exports = class idex extends Exchange { const entry = response[i]; const currencyId = this.safeString (entry, 'asset'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (entry, 'quantity'); - const free = this.safeFloat (entry, 'availableForTrade'); - const used = this.safeFloat (entry, 'locked'); - result[code] = { - 'free': free, - 'used': used, - 'total': total, - }; + const account = this.account (); + account['total'] = this.safeString (entry, 'quantity'); + account['free'] = this.safeString (entry, 'availableForTrade'); + account['used'] = this.safeString (entry, 'locked'); + result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -82975,10 +80899,10 @@ module.exports = class idex extends Exchange { const symbol = this.safeSymbol (marketId, market, '-'); const trades = this.parseTrades (fills, market); const type = this.safeString (order, 'type'); - const amount = this.safeFloat (order, 'originalQuantity'); - const filled = this.safeFloat (order, 'executedQuantity'); - const average = this.safeFloat (order, 'avgExecutionPrice'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'originalQuantity'); + const filled = this.safeNumber (order, 'executedQuantity'); + const average = this.safeNumber (order, 'avgExecutionPrice'); + const price = this.safeNumber (order, 'price'); const rawStatus = this.safeString (order, 'status'); const status = this.parseOrderStatus (rawStatus); const fee = { @@ -83087,7 +81011,7 @@ module.exports = class idex extends Exchange { throw new NotSupported (this.id + ' quoteOrderQuantity is not supported for ' + type + ' orders, only supported for market orders'); } amountEnum = 1; - amount = this.safeFloat (params, 'quoteOrderQuantity'); + amount = this.safeNumber (params, 'quoteOrderQuantity'); } const sideEnum = (side === 'buy') ? 0 : 1; const walletBytes = this.remove0xPrefix (this.walletAddress); @@ -83390,13 +81314,13 @@ module.exports = class idex extends Exchange { } const id = this.safeString2 (transaction, 'depositId', 'withdrawId'); const code = this.safeCurrencyCode (this.safeString (transaction, 'asset'), currency); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const txid = this.safeString (transaction, 'txId'); const timestamp = this.safeInteger (transaction, 'txTime'); let fee = undefined; if ('fee' in transaction) { fee = { - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), 'currency': 'ETH', }; } @@ -83454,12 +81378,13 @@ module.exports = class idex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],99:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],96:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -83583,11 +81508,11 @@ module.exports = class independentreserve extends Exchange { const currencyId = this.safeString (balance, 'CurrencyCode'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'AvailableBalance'); - account['total'] = this.safeFloat (balance, 'TotalBalance'); + account['free'] = this.safeString (balance, 'AvailableBalance'); + account['total'] = this.safeString (balance, 'TotalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -83608,16 +81533,16 @@ module.exports = class independentreserve extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'LastPrice'); + const last = this.safeNumber (ticker, 'LastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'DayHighestPrice'), - 'low': this.safeFloat (ticker, 'DayLowestPrice'), - 'bid': this.safeFloat (ticker, 'CurrentHighestBidPrice'), + 'high': this.safeNumber (ticker, 'DayHighestPrice'), + 'low': this.safeNumber (ticker, 'DayLowestPrice'), + 'bid': this.safeNumber (ticker, 'CurrentHighestBidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'CurrentLowestOfferPrice'), + 'ask': this.safeNumber (ticker, 'CurrentLowestOfferPrice'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -83626,8 +81551,8 @@ module.exports = class independentreserve extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'DayAvgPrice'), - 'baseVolume': this.safeFloat (ticker, 'DayVolumeXbtInSecondaryCurrrency'), + 'average': this.safeNumber (ticker, 'DayAvgPrice'), + 'baseVolume': this.safeNumber (ticker, 'DayVolumeXbtInSecondaryCurrrency'), 'quoteVolume': undefined, 'info': ticker, }; @@ -83706,20 +81631,10 @@ module.exports = class independentreserve extends Exchange { orderType = 'limit'; } const timestamp = this.parse8601 (this.safeString (order, 'CreatedTimestampUtc')); - const amount = this.safeFloat2 (order, 'VolumeOrdered', 'Volume'); - let filled = this.safeFloat (order, 'VolumeFilled'); - let remaining = this.safeFloat (order, 'Outstanding'); - if (filled === undefined) { - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (0, amount - remaining); - } - } - if (remaining === undefined) { - if ((filled !== undefined) && (amount !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const feeRate = this.safeFloat (order, 'FeePercent'); + const amount = this.safeNumber2 (order, 'VolumeOrdered', 'Volume'); + const filled = this.safeNumber (order, 'VolumeFilled'); + const remaining = this.safeNumber (order, 'Outstanding'); + const feeRate = this.safeNumber (order, 'FeePercent'); let feeCost = undefined; if (feeRate !== undefined) { feeCost = feeRate * filled; @@ -83731,10 +81646,10 @@ module.exports = class independentreserve extends Exchange { }; const id = this.safeString (order, 'OrderGuid'); const status = this.parseOrderStatus (this.safeString (order, 'Status')); - const cost = this.safeFloat (order, 'Value'); - const average = this.safeFloat (order, 'AvgPrice'); - const price = this.safeFloat (order, 'Price', average); - return { + const cost = this.safeNumber (order, 'Value'); + const average = this.safeNumber (order, 'AvgPrice'); + const price = this.safeNumber (order, 'Price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -83756,7 +81671,7 @@ module.exports = class independentreserve extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -83844,14 +81759,11 @@ module.exports = class independentreserve extends Exchange { const timestamp = this.parse8601 (trade['TradeTimestampUtc']); const id = this.safeString (trade, 'TradeGuid'); const orderId = this.safeString (trade, 'OrderGuid'); - const price = this.safeFloat2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); - const amount = this.safeFloat2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); + const amountString = this.safeString2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const baseId = this.safeString (trade, 'PrimaryCurrencyCode'); const quoteId = this.safeString (trade, 'SecondaryCurrencyCode'); let marketId = undefined; @@ -83964,13 +81876,14 @@ module.exports = class independentreserve extends Exchange { } }; -},{"./base/Exchange":6}],100:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],97:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, InvalidOrder, OrderNotFound, AuthenticationError, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -84131,7 +82044,7 @@ module.exports = class indodax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const taker = this.safeFloat (market, 'trade_fee_percent'); + const taker = this.safeNumber (market, 'trade_fee_percent'); const isMaintenance = this.safeInteger (market, 'is_maintenance'); const active = (isMaintenance) ? false : true; const pricePrecision = this.safeInteger (market, 'price_round'); @@ -84141,11 +82054,11 @@ module.exports = class indodax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'trade_min_traded_currency'), + 'min': this.safeNumber (market, 'trade_min_traded_currency'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'trade_min_base_currency'), + 'min': this.safeNumber (market, 'trade_min_base_currency'), 'max': undefined, }, 'cost': { @@ -84183,11 +82096,11 @@ module.exports = class indodax extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (used, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (used, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -84224,16 +82137,16 @@ module.exports = class indodax extends Exchange { const timestamp = this.safeTimestamp (ticker, 'server_time'); const baseVolume = 'vol_' + market['baseId'].toLowerCase (); const quoteVolume = 'vol_' + market['quoteId'].toLowerCase (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -84243,8 +82156,8 @@ module.exports = class indodax extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, baseVolume), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, baseVolume), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -84258,14 +82171,11 @@ module.exports = class indodax extends Exchange { } const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -84320,7 +82230,7 @@ module.exports = class indodax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status', 'open')); let symbol = undefined; let cost = undefined; - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let amount = undefined; let remaining = undefined; let filled = undefined; @@ -84334,18 +82244,18 @@ module.exports = class indodax extends Exchange { if ((market['baseId'] === 'idr') && ('remain_rp' in order)) { baseId = 'rp'; } - cost = this.safeFloat (order, 'order_' + quoteId); + cost = this.safeNumber (order, 'order_' + quoteId); if (cost) { amount = cost / price; - const remainingCost = this.safeFloat (order, 'remain_' + quoteId); + const remainingCost = this.safeNumber (order, 'remain_' + quoteId); if (remainingCost !== undefined) { remaining = remainingCost / price; filled = amount - remaining; } } else { - amount = this.safeFloat (order, 'order_' + baseId); + amount = this.safeNumber (order, 'order_' + baseId); cost = price * amount; - remaining = this.safeFloat (order, 'remain_' + baseId); + remaining = this.safeNumber (order, 'remain_' + baseId); filled = amount - remaining; } } @@ -84585,13 +82495,14 @@ module.exports = class indodax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],101:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],98:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -84702,25 +82613,25 @@ module.exports = class itbit extends Exchange { throw new ExchangeError (this.id + ' fetchTicker returned a bad response: ' + this.json (ticker)); } const timestamp = this.parse8601 (serverTimeUTC); - const vwap = this.safeFloat (ticker, 'vwap24h'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); + const vwap = this.safeNumber (ticker, 'vwap24h'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'openToday'), + 'open': this.safeNumber (ticker, 'openToday'), 'close': last, 'last': last, 'previousClose': undefined, @@ -84767,23 +82678,20 @@ module.exports = class itbit extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const side = this.safeString (trade, 'direction'); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'commissionPaid'); + let feeCost = this.safeNumber (trade, 'commissionPaid'); const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - let rebatesApplied = this.safeFloat (trade, 'rebatesApplied'); + let rebatesApplied = this.safeNumber (trade, 'rebatesApplied'); if (rebatesApplied !== undefined) { rebatesApplied = -rebatesApplied; } const rebateCurrencyId = this.safeString (trade, 'rebateCurrency'); const rebateCurrency = this.safeCurrencyCode (rebateCurrencyId); - const price = this.safeFloat2 (trade, 'price', 'rate'); - const amount = this.safeFloat2 (trade, 'currency1Amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'price', 'rate'); + const amountString = this.safeString2 (trade, 'currency1Amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; const marketId = this.safeString (trade, 'instrument'); if (marketId !== undefined) { @@ -84905,7 +82813,7 @@ module.exports = class itbit extends Exchange { 'txid': txnHash, 'type': transactionType, 'status': status, - 'amount': this.safeFloat (item, 'amount'), + 'amount': this.safeNumber (item, 'amount'), 'fee': undefined, 'info': item, }); @@ -85005,11 +82913,11 @@ module.exports = class itbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchWallets (params = {}) { @@ -85100,26 +83008,16 @@ module.exports = class itbit extends Exchange { const type = this.safeString (order, 'type'); const symbol = this.markets_by_id[order['instrument']]['symbol']; const timestamp = this.parse8601 (order['createdTime']); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'amountFilled'); - let remaining = undefined; - let cost = undefined; + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'amountFilled'); const fee = undefined; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'volumeWeightedAveragePrice'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'volumeWeightedAveragePrice'); const clientOrderId = this.safeString (order, 'clientOrderIdentifier'); const id = this.safeString (order, 'id'); const postOnlyString = this.safeString (order, 'postOnly'); const postOnly = (postOnlyString === 'True'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -85134,15 +83032,15 @@ module.exports = class itbit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, // 'trades': this.parseTrades (order['trades'], market), 'trades': undefined, - }; + }); } nonce () { @@ -85240,7 +83138,7 @@ module.exports = class itbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],102:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],99:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -85248,6 +83146,7 @@ module.exports = class itbit extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeNotAvailable, ArgumentsRequired, PermissionDenied, AuthenticationError, ExchangeError, OrderNotFound, DDoSProtection, InvalidNonce, InsufficientFunds, CancelPending, InvalidOrder, InvalidAddress, RateLimitExceeded } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -85540,26 +83439,38 @@ module.exports = class kraken extends Exchange { // } // } // - const keys = Object.keys (response['result']); + const markets = this.safeValue (response, 'result', {}); + const keys = Object.keys (markets); let result = []; for (let i = 0; i < keys.length; i++) { const id = keys[i]; - const market = response['result'][id]; - const baseId = market['base']; - const quoteId = market['quote']; + const market = markets[id]; + const baseId = this.safeString (market, 'base'); + const quoteId = this.safeString (market, 'quote'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const darkpool = id.indexOf ('.d') >= 0; - const symbol = darkpool ? market['altname'] : (base + '/' + quote); + const altname = this.safeString (market, 'altname'); + const symbol = darkpool ? altname : (base + '/' + quote); + const makerFees = this.safeValue (market, 'fees_maker', []); + const firstMakerFee = this.safeValue (makerFees, 0, []); + const firstMakerFeeRate = this.safeNumber (firstMakerFee, 1); let maker = undefined; - if ('fees_maker' in market) { - maker = parseFloat (market['fees_maker'][0][1]) / 100; + if (firstMakerFeeRate !== undefined) { + maker = parseFloat (firstMakerFeeRate) / 100; + } + const takerFees = this.safeValue (market, 'fees', []); + const firstTakerFee = this.safeValue (takerFees, 0, []); + const firstTakerFeeRate = this.safeNumber (firstTakerFee, 1); + let taker = undefined; + if (firstTakerFeeRate !== undefined) { + taker = parseFloat (firstTakerFeeRate) / 100; } const precision = { - 'amount': market['lot_decimals'], - 'price': market['pair_decimals'], + 'amount': this.safeInteger (market, 'lot_decimals'), + 'price': this.safeInteger (market, 'pair_decimals'), }; - const minAmount = this.safeFloat (market, 'ordermin'); + const minAmount = this.safeNumber (market, 'ordermin'); result.push ({ 'id': id, 'symbol': symbol, @@ -85571,7 +83482,7 @@ module.exports = class kraken extends Exchange { 'info': market, 'altname': market['altname'], 'maker': maker, - 'taker': parseFloat (market['fees'][0][1]) / 100, + 'taker': taker, 'active': true, 'precision': precision, 'limits': { @@ -85694,7 +83605,7 @@ module.exports = class kraken extends Exchange { await this.loadMarkets (); this.checkRequiredCredentials (); const response = await this.privatePostTradeVolume (params); - const tradedVolume = this.safeFloat (response['result'], 'volume'); + const tradedVolume = this.safeNumber (response['result'], 'volume'); const tiers = this.fees['trading']['tiers']; let taker = tiers['taker'][1]; let maker = tiers['maker'][1]; @@ -85716,8 +83627,8 @@ module.exports = class kraken extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); const timestamp = this.safeInteger (bidask, 2); return [ price, amount, timestamp ]; } @@ -85755,7 +83666,14 @@ module.exports = class kraken extends Exchange { // } // const result = this.safeValue (response, 'result', {}); - const orderbook = this.safeValue (result, market['id']); + let orderbook = this.safeValue (result, market['id']); + // sometimes kraken returns wsname instead of market id + // https://github.com/ccxt/ccxt/issues/8662 + const marketInfo = this.safeValue (market, 'info', {}); + const wsName = this.safeValue (marketInfo, 'wsname'); + if (wsName !== undefined) { + orderbook = this.safeValue (result, wsName, orderbook); + } return this.parseOrderBook (orderbook); } @@ -85783,7 +83701,7 @@ module.exports = class kraken extends Exchange { 'ask': parseFloat (ticker['a'][0]), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'o'), + 'open': this.safeNumber (ticker, 'o'), 'close': last, 'last': last, 'previousClose': undefined, @@ -85854,11 +83772,11 @@ module.exports = class kraken extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 6), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 6), ]; } @@ -85925,24 +83843,24 @@ module.exports = class kraken extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'asset'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); } else { direction = 'in'; } - const time = this.safeFloat (item, 'time'); + const time = this.safeNumber (item, 'time'); let timestamp = undefined; if (time !== undefined) { timestamp = parseInt (time * 1000); } const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -86066,9 +83984,8 @@ module.exports = class kraken extends Exchange { let timestamp = undefined; let side = undefined; let type = undefined; - let price = undefined; - let amount = undefined; - let cost = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; let orderId = undefined; let fee = undefined; @@ -86077,8 +83994,8 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 2); side = (trade[3] === 's') ? 'sell' : 'buy'; type = (trade[4] === 'l') ? 'limit' : 'market'; - price = this.safeFloat (trade, 0); - amount = this.safeFloat (trade, 1); + priceString = this.safeString (trade, 0); + amountString = this.safeString (trade, 1); const tradeLength = trade.length; if (tradeLength > 6) { id = this.safeString (trade, 6); // artificially added as per #1794 @@ -86099,15 +84016,15 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 'time'); side = this.safeString (trade, 'type'); type = this.safeString (trade, 'ordertype'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'vol'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'vol'); if ('fee' in trade) { let currency = undefined; if (market !== undefined) { currency = market['quote']; } fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': currency, }; } @@ -86115,11 +84032,9 @@ module.exports = class kraken extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': orderId, @@ -86194,10 +84109,10 @@ module.exports = class kraken extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -86226,15 +84141,15 @@ module.exports = class kraken extends Exchange { if (type === 'limit') { request['price'] = this.priceToPrecision (symbol, price); } else if ((type === 'stop-loss') || (type === 'take-profit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice', price); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice', price); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument or a price/stopPrice parameter for a ' + type + ' order'); } else { request['price'] = this.priceToPrecision (symbol, stopPrice); } } else if ((type === 'stop-loss-limit') || (type === 'take-profit-limit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice'); - const limitPrice = this.safeFloat (params, 'price2'); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice'); + const limitPrice = this.safeNumber (params, 'price2'); const stopPriceDefined = (stopPrice !== undefined); const limitPriceDefined = (limitPrice !== undefined); if (stopPriceDefined && limitPriceDefined) { @@ -86343,10 +84258,10 @@ module.exports = class kraken extends Exchange { if (orderDescription !== undefined) { const parts = orderDescription.split (' '); side = this.safeString (parts, 0); - amount = this.safeFloat (parts, 1); + amount = this.safeNumber (parts, 1); marketId = this.safeString (parts, 2); type = this.safeString (parts, 4); - price = this.safeFloat (parts, 5); + price = this.safeNumber (parts, 5); } side = this.safeString (description, 'type', side); type = this.safeString (description, 'ordertype', type); @@ -86360,27 +84275,23 @@ module.exports = class kraken extends Exchange { market = this.getDelistedMarketById (marketId); } const timestamp = this.safeTimestamp (order, 'opentm'); - amount = this.safeFloat (order, 'vol', amount); - const filled = this.safeFloat (order, 'vol_exec'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = amount - filled; - } + amount = this.safeNumber (order, 'vol', amount); + const filled = this.safeNumber (order, 'vol_exec'); let fee = undefined; - const cost = this.safeFloat (order, 'cost'); - price = this.safeFloat (description, 'price', price); + const cost = this.safeNumber (order, 'cost'); + price = this.safeNumber (description, 'price', price); if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (description, 'price2'); + price = this.safeNumber (description, 'price2'); } if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (order, 'price', price); + price = this.safeNumber (order, 'price', price); } - const average = this.safeFloat (order, 'price'); + const average = this.safeNumber (order, 'price'); if (market !== undefined) { symbol = market['symbol']; if ('fee' in order) { const flags = order['oflags']; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); fee = { 'cost': feeCost, 'rate': undefined, @@ -86404,8 +84315,8 @@ module.exports = class kraken extends Exchange { if (rawTrades !== undefined) { trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id }); } - const stopPrice = this.safeFloat (order, 'stopprice'); - return { + const stopPrice = this.safeNumber (order, 'stopprice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -86424,10 +84335,10 @@ module.exports = class kraken extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -86777,10 +84688,10 @@ module.exports = class kraken extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const address = this.safeString (transaction, 'info'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.safeString (transaction, 'type'); // injected from the outside - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost === undefined) { if (type === 'deposit') { feeCost = 0; @@ -86957,7 +84868,7 @@ module.exports = class kraken extends Exchange { throw new ExchangeError (this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)"); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { // 'txid': 'comma delimited list of transaction ids to restrict output to', @@ -87091,13 +85002,14 @@ module.exports = class kraken extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],103:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],100:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -87139,6 +85051,7 @@ module.exports = class kucoin extends Exchange { 'fetchTrades': true, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg', @@ -87146,6 +85059,7 @@ module.exports = class kucoin extends Exchange { 'api': { 'public': 'https://openapi-v2.kucoin.com', 'private': 'https://openapi-v2.kucoin.com', + 'futuresPrivate': 'https://api-futures.kucoin.com', }, 'test': { 'public': 'https://openapi-sandbox.kucoin.com', @@ -87254,6 +85168,15 @@ module.exports = class kucoin extends Exchange { 'stop-order/cancel', ], }, + 'futuresPrivate': { + 'get': [ + 'account-overview', + 'positions', + ], + 'post': [ + 'transfer-out', + ], + }, }, 'timeframes': { '1m': '1min', @@ -87278,6 +85201,7 @@ module.exports = class kucoin extends Exchange { 'order_not_exist_or_not_allow_to_cancel': InvalidOrder, // {"code":"400100","msg":"order_not_exist_or_not_allow_to_cancel"} 'Order size below the minimum requirement.': InvalidOrder, // {"code":"400100","msg":"Order size below the minimum requirement."} 'The withdrawal amount is below the minimum requirement.': ExchangeError, // {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."} + 'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, // {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"} '400': BadRequest, '401': AuthenticationError, '403': NotSupported, @@ -87334,9 +85258,7 @@ module.exports = class kucoin extends Exchange { 'version': 'v1', 'symbolSeparator': '-', 'fetchMyTradesMethod': 'private_get_fills', - 'fetchBalance': { - 'type': 'trade', // or 'main' - }, + 'fetchBalance': 'trade', // endpoint versions 'versions': { 'public': { @@ -87356,6 +85278,25 @@ module.exports = class kucoin extends Exchange { 'accounts/sub-transfer': 'v2', }, }, + 'futuresPrivate': { + 'GET': { + 'account-overview': 'v1', + 'positions': 'v1', + }, + 'POST': { + 'transfer-out': 'v2', + }, + }, + }, + 'accountsByType': { + 'trade': 'trade', + 'trading': 'trade', + 'margin': 'margin', + 'main': 'main', + 'futures': 'contract', + 'contract': 'contract', + 'pool': 'pool', + 'pool-x': 'pool', }, }, }); @@ -87436,11 +85377,11 @@ module.exports = class kucoin extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const active = this.safeValue (market, 'enableTrading'); - const baseMaxSize = this.safeFloat (market, 'baseMaxSize'); - const baseMinSize = this.safeFloat (market, 'baseMinSize'); - const quoteMaxSize = this.safeFloat (market, 'quoteMaxSize'); - const quoteMinSize = this.safeFloat (market, 'quoteMinSize'); - // const quoteIncrement = this.safeFloat (market, 'quoteIncrement'); + const baseMaxSize = this.safeNumber (market, 'baseMaxSize'); + const baseMinSize = this.safeNumber (market, 'baseMinSize'); + const quoteMaxSize = this.safeNumber (market, 'quoteMaxSize'); + const quoteMinSize = this.safeNumber (market, 'quoteMinSize'); + // const quoteIncrement = this.safeNumber (market, 'quoteIncrement'); const precision = { 'amount': this.precisionFromString (this.safeString (market, 'baseIncrement')), 'price': this.precisionFromString (this.safeString (market, 'priceIncrement')), @@ -87451,7 +85392,7 @@ module.exports = class kucoin extends Exchange { 'max': baseMaxSize, }, 'price': { - 'min': this.safeFloat (market, 'priceIncrement'), + 'min': this.safeNumber (market, 'priceIncrement'), 'max': quoteMaxSize / baseMinSize, }, 'cost': { @@ -87502,7 +85443,7 @@ module.exports = class kucoin extends Exchange { const precision = this.safeInteger (entry, 'precision'); const isWithdrawEnabled = this.safeValue (entry, 'isWithdrawEnabled', false); const isDepositEnabled = this.safeValue (entry, 'isDepositEnabled', false); - const fee = this.safeFloat (entry, 'withdrawalMinFee'); + const fee = this.safeNumber (entry, 'withdrawalMinFee'); const active = (isWithdrawEnabled && isDepositEnabled); result[code] = { 'id': id, @@ -87569,7 +85510,7 @@ module.exports = class kucoin extends Exchange { const response = await this.privateGetWithdrawalsQuotas (this.extend (request, params)); const data = response['data']; const withdrawFees = {}; - withdrawFees[code] = this.safeFloat (data, 'withdrawMinFee'); + withdrawFees[code] = this.safeNumber (data, 'withdrawMinFee'); return { 'info': response, 'withdraw': withdrawFees, @@ -87616,35 +85557,35 @@ module.exports = class kucoin extends Exchange { // "mark": 0 // } // - let percentage = this.safeFloat (ticker, 'changeRate'); + let percentage = this.safeNumber (ticker, 'changeRate'); if (percentage !== undefined) { percentage = percentage * 100; } - const last = this.safeFloat2 (ticker, 'last', 'lastTradedPrice'); + const last = this.safeNumber2 (ticker, 'last', 'lastTradedPrice'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'vol'); - const quoteVolume = this.safeFloat (ticker, 'volValue'); + const baseVolume = this.safeNumber (ticker, 'vol'); + const quoteVolume = this.safeNumber (ticker, 'volValue'); const vwap = this.vwap (baseVolume, quoteVolume); const timestamp = this.safeInteger2 (ticker, 'time', 'datetime'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'changePrice'), + 'change': this.safeNumber (ticker, 'changePrice'), 'percentage': percentage, - 'average': this.safeFloat (ticker, 'averagePrice'), + 'average': this.safeNumber (ticker, 'averagePrice'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -87728,11 +85669,11 @@ module.exports = class kucoin extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -87930,16 +85871,18 @@ module.exports = class kucoin extends Exchange { // 'marginMode': 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned // 'autoBorrow': false, // The system will first borrow you funds at the optimal interest rate and then place an order for you }; - if (type !== 'market') { - request['price'] = this.priceToPrecision (symbol, price); - request['size'] = this.amountToPrecision (symbol, amount); - } else { - if (this.safeValue (params, 'quoteAmount')) { - // used to create market order by quote amount - https://github.com/ccxt/ccxt/issues/4876 - request['funds'] = this.amountToPrecision (symbol, amount); + const quoteAmount = this.safeNumber2 (params, 'cost', 'funds'); + if (type === 'market') { + if (quoteAmount !== undefined) { + params = this.omit (params, [ 'cost', 'funds' ]); + // kucoin uses base precision even for quote values + request['funds'] = this.amountToPrecision (symbol, quoteAmount); } else { request['size'] = this.amountToPrecision (symbol, amount); } + } else { + request['price'] = this.priceToPrecision (symbol, price); + request['size'] = this.amountToPrecision (symbol, amount); } const response = await this.privatePostOrders (this.extend (request, params)); // @@ -87973,8 +85916,10 @@ module.exports = class kucoin extends Exchange { 'fee': undefined, 'trades': undefined, }; - if (!this.safeValue (params, 'quoteAmount')) { + if (quoteAmount === undefined) { order['amount'] = amount; + } else { + order['cost'] = quoteAmount; } return order; } @@ -88150,15 +86095,18 @@ module.exports = class kucoin extends Exchange { const type = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'createdAt'); const datetime = this.iso8601 (timestamp); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); + if (price === 0.0) { + // market orders + price = undefined; + } const side = this.safeString (order, 'side'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (order, 'fee'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'dealSize'); - const cost = this.safeFloat (order, 'dealFunds'); - const remaining = amount - filled; + const feeCost = this.safeNumber (order, 'fee'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'dealSize'); + const cost = this.safeNumber (order, 'dealFunds'); // bool const isActive = this.safeValue (order, 'isActive', false); const cancelExist = this.safeValue (order, 'cancelExist', false); @@ -88168,20 +86116,11 @@ module.exports = class kucoin extends Exchange { 'currency': feeCurrency, 'cost': feeCost, }; - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const clientOrderId = this.safeString (order, 'clientOid'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': orderId, 'clientOrderId': clientOrderId, 'symbol': symbol, @@ -88194,7 +86133,7 @@ module.exports = class kucoin extends Exchange { 'stopPrice': stopPrice, 'cost': cost, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'timestamp': timestamp, 'datetime': datetime, 'fee': fee, @@ -88203,7 +86142,7 @@ module.exports = class kucoin extends Exchange { 'lastTradeTimestamp': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -88404,7 +86343,6 @@ module.exports = class kucoin extends Exchange { const id = this.safeString2 (trade, 'tradeId', 'id'); const orderId = this.safeString (trade, 'orderId'); const takerOrMaker = this.safeString (trade, 'liquidity'); - const amount = this.safeFloat2 (trade, 'size', 'amount'); let timestamp = this.safeInteger (trade, 'time'); if (timestamp !== undefined) { timestamp = parseInt (timestamp / 1000000); @@ -88415,10 +86353,13 @@ module.exports = class kucoin extends Exchange { timestamp = timestamp * 1000; } } - const price = this.safeFloat2 (trade, 'price', 'dealPrice'); + const priceString = this.safeString2 (trade, 'price', 'dealPrice'); + const amountString = this.safeString2 (trade, 'size', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const side = this.safeString (trade, 'side'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); let feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -88430,20 +86371,16 @@ module.exports = class kucoin extends Exchange { fee = { 'cost': feeCost, 'currency': feeCurrency, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } let type = this.safeString (trade, 'type'); if (type === 'match') { type = undefined; } - let cost = this.safeFloat2 (trade, 'funds', 'dealValue'); + let cost = this.safeNumber2 (trade, 'funds', 'dealValue'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'info': trade, @@ -88539,7 +86476,7 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); let address = this.safeString (transaction, 'address'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let txid = this.safeString (transaction, 'walletTxId'); if (txid !== undefined) { const txidParts = txid.split ('@'); @@ -88557,7 +86494,7 @@ module.exports = class kucoin extends Exchange { const rawStatus = this.safeString (transaction, 'status'); const status = this.parseTransactionStatus (rawStatus); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { let rate = undefined; if (amount !== undefined) { @@ -88738,45 +86675,180 @@ module.exports = class kucoin extends Exchange { async fetchBalance (params = {}) { await this.loadMarkets (); - let type = undefined; - const request = {}; - if ('type' in params) { - type = params['type']; - if (type !== undefined) { - request['type'] = type; - } - params = this.omit (params, 'type'); + const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'trade'); + const requestedType = this.safeString (params, 'type', defaultType); + const accountsByType = this.safeValue (this.options, 'accountsByType'); + const type = this.safeString (accountsByType, requestedType); + if (type === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' type must be one of ' + keys.join (', ')); + } + params = this.omit (params, 'type'); + if (type === 'contract') { + // futures api requires a futures apiKey + // only fetches one balance at a time + // by default it will only fetch the BTC balance of the futures account + // you can send 'currency' in params to fetch other currencies + // fetchBalance ({ 'type': 'futures', 'currency': 'USDT' }) + const response = await this.futuresPrivateGetAccountOverview (params); + // + // { + // code: '200000', + // data: { + // accountEquity: 0.00005, + // unrealisedPNL: 0, + // marginBalance: 0.00005, + // positionMargin: 0, + // orderMargin: 0, + // frozenFunds: 0, + // availableBalance: 0.00005, + // currency: 'XBT' + // } + // } + // + const data = this.safeValue (response, 'data'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (data, 'availableBalance'); + account['total'] = this.safeString (data, 'accountEquity'); + const result = { 'info': response }; + result[code] = account; + return this.parseBalance (result, false); } else { - const options = this.safeValue (this.options, 'fetchBalance', {}); - type = this.safeString (options, 'type', 'trade'); - } - const response = await this.privateGetAccounts (this.extend (request, params)); - // - // { - // "code":"200000", - // "data":[ - // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, - // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, - // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - const result = { 'info': response }; - for (let i = 0; i < data.length; i++) { - const balance = data[i]; - const balanceType = this.safeString (balance, 'type'); - if (balanceType === type) { - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'holds'); - result[code] = account; + const request = { + 'type': type, + }; + const response = await this.privateGetAccounts (this.extend (request, params)); + // + // { + // "code":"200000", + // "data":[ + // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, + // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, + // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + const result = { 'info': response }; + for (let i = 0; i < data.length; i++) { + const balance = data[i]; + const balanceType = this.safeString (balance, 'type'); + if (balanceType === type) { + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'holds'); + result[code] = account; + } } + return this.parseBalance (result, false); + } + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const requestedAmount = this.currencyToPrecision (code, amount); + const accountsById = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsById, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsById, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + if (fromId === 'contract') { + if (toId !== 'main') { + throw new ExchangeError (this.id + ' only supports transferring from futures account to main account'); + } + const request = { + 'currency': currency['id'], + 'amount': requestedAmount, + }; + if (!('bizNo' in params)) { + // it doesn't like more than 24 characters + request['bizNo'] = this.uuid22 (); + } + const response = await this.futuresPrivatePostTransferOut (this.extend (request, params)); + // + // { + // code: '200000', + // data: { + // applyId: '605a87217dff1500063d485d', + // bizNo: 'bcd6e5e1291f4905af84dc', + // payAccountType: 'CONTRACT', + // payTag: 'DEFAULT', + // remark: '', + // recAccountType: 'MAIN', + // recTag: 'DEFAULT', + // recRemark: '', + // recSystem: 'KUCOIN', + // status: 'PROCESSING', + // currency: 'XBT', + // amount: '0.00001', + // fee: '0', + // sn: '573688685663948', + // reason: '', + // createdAt: 1616545569000, + // updatedAt: 1616545569000 + // } + // } + // + const data = this.safeValue (response, 'data'); + const timestamp = this.safeInteger (data, 'createdAt'); + const id = this.safeString (data, 'applyId'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const amount = this.safeNumber (data, 'amount'); + const rawStatus = this.safeString (data, 'status'); + let status = undefined; + if (rawStatus === 'PROCESSING') { + status = 'pending'; + } + return { + 'info': response, + 'currency': code, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'amount': amount, + 'fromAccount': fromId, + 'toAccount': toId, + 'id': id, + 'status': status, + }; + } else { + const request = { + 'currency': currency['id'], + 'from': fromId, + 'to': toId, + 'amount': requestedAmount, + }; + if (!('clientOid' in params)) { + request['clientOid'] = this.uuid (); + } + const response = await this.privatePostAccountsInnerTransfer (this.extend (request, params)); + // { code: '200000', data: { orderId: '605a6211e657f00006ad0ad6' } } + const data = this.safeValue (response, 'data'); + const id = this.safeString (data, 'orderId'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'currency': code, + 'amount': requestedAmount, + 'fromAccount': fromId, + 'toAccount': toId, + 'status': undefined, + }; } - return this.parseBalance (result); } async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -88864,11 +86936,11 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'code': code, }; - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'balance'); const direction = this.safeString (item, 'direction'); let before = undefined; if (after !== undefined && amount !== undefined) { @@ -88918,6 +86990,94 @@ module.exports = class kucoin extends Exchange { return this.safeString (types, type, type); } + async fetchPositions (symbols = undefined, params = {}) { + const response = await this.futuresPrivateGetPositions (params); + // + // { + // code: '200000', + // data: [ + // { + // id: '605a9772a229ab0006408258', + // symbol: 'XBTUSDTM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746099, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54371.92, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'USDT', + // isInverse: false + // }, + // { + // id: '605a9772026ac900066550df', + // symbol: 'XBTUSDM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746110, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54354.76, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'XBT', + // isInverse: true + // } + // ] + // } + // + return this.safeValue (response, 'data', response); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { // // the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint @@ -88934,16 +87094,16 @@ module.exports = class kucoin extends Exchange { let endpart = ''; headers = (headers !== undefined) ? headers : {}; if (Object.keys (query).length) { - if (method !== 'GET') { + if ((method === 'GET') || (method === 'DELETE')) { + endpoint += '?' + this.urlencode (query); + } else { body = this.json (query); endpart = body; headers['Content-Type'] = 'application/json'; - } else { - endpoint += '?' + this.urlencode (query); } } const url = this.urls['api'][api] + endpoint; - if (api === 'private') { + if ((api === 'private') || (api === 'futuresPrivate')) { this.checkRequiredCredentials (); const timestamp = this.nonce ().toString (); headers = this.extend ({ @@ -88986,23 +87146,24 @@ module.exports = class kucoin extends Exchange { // { code: '200000', data: { ... }} // const errorCode = this.safeString (response, 'code'); - const message = this.safeString (response, 'msg'); - this.throwExactlyMatchedException (this.exceptions['exact'], message, message); - this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, message); + const message = this.safeString (response, 'msg', ''); + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, this.id + ' ' + message); } }; -},{"./base/Exchange":6,"./base/errors":8}],104:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],101:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- -const acx = require ('./acx.js'); -const { ArgumentsRequired } = require ('./base/errors'); +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, InsufficientFunds, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class kuna extends acx { +module.exports = class kuna extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'kuna', @@ -89012,14 +87173,24 @@ module.exports = class kuna extends acx { 'version': 'v2', 'has': { 'CORS': false, - 'fetchTickers': true, + 'cancelOrder': true, + 'createOrder': true, + 'fetchBalance': true, + 'fetchMarkets': true, + 'fetchMyTrades': true, 'fetchOHLCV': 'emulated', 'fetchOpenOrders': true, - 'fetchMyTrades': true, + 'fetchOrder': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchTime': true, + 'fetchTrades': true, 'withdraw': false, }, 'timeframes': undefined, 'urls': { + 'extension': '.json', 'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4', 'logo': 'https://user-images.githubusercontent.com/51840849/87153927-f0578b80-c2c0-11ea-84b6-74612568e9e1.jpg', 'api': 'https://kuna.io', @@ -89027,8 +87198,47 @@ module.exports = class kuna extends acx { 'doc': 'https://kuna.io/documents/api', 'fees': 'https://kuna.io/documents/api', }, + 'api': { + 'public': { + 'get': [ + 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. + 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator + 'k', // Get OHLC(k line) of specific market + 'markets', // Get all available markets + 'order_book', // Get the order book of specified market + 'order_book/{market}', + 'tickers', // Get ticker of all markets + 'tickers/{market}', // Get ticker of specific market + 'timestamp', // Get server current time, in seconds since Unix epoch + 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. + 'trades/{market}', + ], + }, + 'private': { + 'get': [ + 'members/me', // Get your profile and accounts info + 'deposits', // Get your deposits history + 'deposit', // Get details of specific deposit + 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. + 'orders', // Get your orders, results is paginated + 'order', // Get information of specified order + 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. + 'withdraws', // Get your cryptocurrency withdraws + 'withdraw', // Get your cryptocurrency withdraw + ], + 'post': [ + 'orders', // Create a Sell/Buy order + 'orders/multi', // Create multiple sell/buy orders + 'orders/clear', // Cancel all my orders + 'order/delete', // Cancel an order + 'withdraw', // Create a withdraw + ], + }, + }, 'fees': { 'trading': { + 'tierBased': false, + 'percentage': true, 'taker': 0.25 / 100, 'maker': 0.25 / 100, }, @@ -89051,9 +87261,24 @@ module.exports = class kuna extends acx { }, }, }, + 'commonCurrencies': { + 'PLA': 'Plair', + }, + 'exceptions': { + '2002': InsufficientFunds, + '2003': OrderNotFound, + }, }); } + async fetchTime (params = {}) { + const response = await this.publicGetTimestamp (params); + // + // 1594911427 + // + return response * 1000; + } + async fetchMarkets (params = {}) { const quotes = [ 'btc', 'eth', 'eurs', 'rub', 'uah', 'usd', 'usdt', 'gol' ]; const pricePrecisions = { @@ -89109,24 +87334,100 @@ module.exports = class kuna extends acx { return markets; } - async fetchL3OrderBook (symbol, limit = undefined, params = {}) { - return await this.fetchOrderBook (symbol, limit, params); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); - } + async fetchOrderBook (symbol, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; - const response = await this.privateGetOrders (this.extend (request, params)); - // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder - // with order cache + fetchOpenOrders - // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX - return this.parseOrders (response, market, since, limit); + if (limit !== undefined) { + request['limit'] = limit; // default = 300 + } + const orderbook = await this.publicGetDepth (this.extend (request, params)); + const timestamp = this.safeTimestamp (orderbook, 'timestamp'); + return this.parseOrderBook (orderbook, timestamp); + } + + parseTicker (ticker, market = undefined) { + const timestamp = this.safeTimestamp (ticker, 'at'); + ticker = ticker['ticker']; + let symbol = undefined; + if (market) { + symbol = market['symbol']; + } + const last = this.safeNumber (ticker, 'last'); + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'bidVolume': undefined, + 'ask': this.safeNumber (ticker, 'sell'), + 'askVolume': undefined, + 'vwap': undefined, + 'open': this.safeNumber (ticker, 'open'), + 'close': last, + 'last': last, + 'previousClose': undefined, + 'change': undefined, + 'percentage': undefined, + 'average': undefined, + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const response = await this.publicGetTickers (params); + const ids = Object.keys (response); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + let market = undefined; + let symbol = id; + if (id in this.markets_by_id) { + market = this.markets_by_id[id]; + symbol = market['symbol']; + } else { + let base = id.slice (0, 3); + let quote = id.slice (3, 6); + base = base.toUpperCase (); + quote = quote.toUpperCase (); + base = this.safeCurrencyCode (base); + quote = this.safeCurrencyCode (quote); + symbol = base + '/' + quote; + } + result[symbol] = this.parseTicker (response[id], market); + } + return this.filterByArray (result, 'symbol', symbols); + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTickersMarket (this.extend (request, params)); + return this.parseTicker (response, market); + } + + async fetchL3OrderBook (symbol, limit = undefined, params = {}) { + return await this.fetchOrderBook (symbol, limit, params); + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTrades (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); } parseTrade (trade, market = undefined) { @@ -89143,9 +87444,14 @@ module.exports = class kuna extends acx { }; side = this.safeString (sideMap, side, side); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_id'); const id = this.safeString (trade, 'id'); return { @@ -89165,29 +87471,6 @@ module.exports = class kuna extends acx { }; } - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); - } - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.privateGetTradesMy (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const trades = await this.fetchTrades (symbol, since, limit, params); @@ -89206,15 +87489,210 @@ module.exports = class kuna extends acx { } return result; } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + const response = await this.privateGetMembersMe (params); + const balances = this.safeValue (response, 'accounts'); + const result = { 'info': balances }; + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'market': this.marketId (symbol), + 'side': side, + 'volume': amount.toString (), + 'ord_type': type, + }; + if (type === 'limit') { + request['price'] = price.toString (); + } + const response = await this.privatePostOrders (this.extend (request, params)); + const marketId = this.safeValue (response, 'market'); + const market = this.safeValue (this.markets_by_id, marketId); + return this.parseOrder (response, market); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': id, + }; + const response = await this.privatePostOrderDelete (this.extend (request, params)); + const order = this.parseOrder (response); + const status = order['status']; + if (status === 'closed' || status === 'canceled') { + throw new OrderNotFound (this.id + ' ' + this.json (order)); + } + return order; + } + + parseOrderStatus (status) { + const statuses = { + 'done': 'closed', + 'wait': 'open', + 'cancel': 'canceled', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + const marketId = this.safeString (order, 'market'); + const symbol = this.safeSymbol (marketId, market); + const timestamp = this.parse8601 (this.safeString (order, 'created_at')); + const status = this.parseOrderStatus (this.safeString (order, 'state')); + const type = this.safeString (order, 'type'); + const side = this.safeString (order, 'side'); + const id = this.safeString (order, 'id'); + return this.safeOrder ({ + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': undefined, + 'status': status, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': this.safeNumber (order, 'price'), + 'stopPrice': undefined, + 'amount': this.safeNumber (order, 'volume'), + 'filled': this.safeNumber (order, 'executed_volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'trades': undefined, + 'fee': undefined, + 'info': order, + 'cost': undefined, + 'average': undefined, + }); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': parseInt (id), + }; + const response = await this.privateGetOrder (this.extend (request, params)); + return this.parseOrder (response); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetOrders (this.extend (request, params)); + // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder + // with order cache + fetchOpenOrders + // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX + return this.parseOrders (response, market, since, limit); + } + + async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetTradesMy (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); + } + + nonce () { + return this.milliseconds (); + } + + encodeParams (params) { + if ('orders' in params) { + const orders = params['orders']; + let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); + for (let i = 0; i < orders.length; i++) { + const order = orders[i]; + const keys = Object.keys (order); + for (let k = 0; k < keys.length; k++) { + const key = keys[k]; + const value = order[key]; + query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); + } + } + return query; + } + return this.urlencode (this.keysort (params)); + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let request = '/api/' + this.version + '/' + this.implodeParams (path, params); + if ('extension' in this.urls) { + request += this.urls['extension']; + } + const query = this.omit (params, this.extractParams (path)); + let url = this.urls['api'] + request; + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const nonce = this.nonce ().toString (); + const query = this.encodeParams (this.extend ({ + 'access_key': this.apiKey, + 'tonce': nonce, + }, params)); + const auth = method + '|' + request + '|' + query; + const signed = this.hmac (this.encode (auth), this.encode (this.secret)); + const suffix = query + '&signature=' + signed; + if (method === 'GET') { + url += '?' + suffix; + } else { + body = suffix; + headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; + } + } + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; + } + if (code === 400) { + const error = this.safeValue (response, 'error'); + const errorCode = this.safeString (error, 'code'); + const feedback = this.id + ' ' + this.json (response); + this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); + // fallback to default error handler + } + } }; -},{"./acx.js":4,"./base/errors":8}],105:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],102:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89323,10 +87801,10 @@ module.exports = class lakebtc extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -89344,16 +87822,16 @@ module.exports = class lakebtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -89363,7 +87841,7 @@ module.exports = class lakebtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -89394,14 +87872,11 @@ module.exports = class lakebtc extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -89538,14 +88013,14 @@ module.exports = class lakebtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],106:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],103:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, DDoSProtection, BadRequest, AuthenticationError } = require ('./base/errors'); -const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89626,6 +88101,7 @@ module.exports = class latoken extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.1 / 100, @@ -89710,7 +88186,7 @@ module.exports = class latoken extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minQty'), + 'min': this.safeNumber (market, 'minQty'), 'max': undefined, }, 'price': { @@ -89760,7 +88236,7 @@ module.exports = class latoken extends Exchange { const numericId = this.safeInteger (currency, 'currencyId'); const code = this.safeCurrencyCode (id); const precision = this.safeInteger (currency, 'precission'); - const fee = this.safeFloat (currency, 'fee'); + const fee = this.safeNumber (currency, 'fee'); const active = undefined; result[code] = { 'id': id, @@ -89794,27 +88270,6 @@ module.exports = class latoken extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const response = await this.privateGetAccountBalances (params); @@ -89838,17 +88293,15 @@ module.exports = class latoken extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const frozen = this.safeFloat (balance, 'frozen'); - const pending = this.safeFloat (balance, 'pending'); - const used = this.sum (frozen, pending); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': used, - 'total': this.safeFloat (balance, 'amount'), - }; + const frozen = this.safeString (balance, 'frozen'); + const pending = this.safeString (balance, 'pending'); + const account = this.account (); + account['used'] = Precise.stringAdd (frozen, pending); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -89893,20 +88346,20 @@ module.exports = class latoken extends Exchange { // const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; if (open !== undefined && close !== undefined) { change = close - open; } - const percentage = this.safeFloat (ticker, 'priceChange'); + const percentage = this.safeNumber (ticker, 'priceChange'); const timestamp = this.nonce (); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'low': this.safeFloat (ticker, 'low'), - 'high': this.safeFloat (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -89920,7 +88373,7 @@ module.exports = class latoken extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -90004,22 +88457,19 @@ module.exports = class latoken extends Exchange { timestamp *= 1000; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'orderId'); - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -90154,29 +88604,17 @@ module.exports = class latoken extends Exchange { const symbol = this.safeSymbol (marketId, market); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executedAmount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executedAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderStatus')); - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const timeFilled = this.safeTimestamp (order, 'timeFilled'); let lastTradeTimestamp = undefined; if ((timeFilled !== undefined) && (timeFilled > 0)) { lastTradeTimestamp = timeFilled; } const clientOrderId = this.safeString (order, 'cliOrdId'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -90191,14 +88629,14 @@ module.exports = class latoken extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'average': undefined, - 'remaining': remaining, + 'remaining': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -90428,13 +88866,14 @@ module.exports = class latoken extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],107:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],104:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -90632,8 +89071,8 @@ module.exports = class lbank extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const info = ticker; ticker = info['ticker']; - const last = this.safeFloat (ticker, 'latest'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'latest'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; if (percentage !== undefined) { const relativeChange = this.sum (1, percentage / 100); @@ -90654,8 +89093,8 @@ module.exports = class lbank extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -90668,8 +89107,8 @@ module.exports = class lbank extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'turnover'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'turnover'), 'info': info, }; } @@ -90719,17 +89158,15 @@ module.exports = class lbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (trade, 'date_ms'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'tid'); const type = undefined; - const side = this.safeString (trade, 'type'); + let side = this.safeString (trade, 'type'); + side = side.replace ('_market', ''); return { 'id': id, 'info': this.safeValue (trade, 'info', trade), @@ -90777,11 +89214,11 @@ module.exports = class lbank extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -90846,12 +89283,12 @@ module.exports = class lbank extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (freeze, currencyId); - account['total'] = this.safeFloat (asset, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (freeze, currencyId); + account['total'] = this.safeString (asset, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -90879,35 +89316,20 @@ module.exports = class lbank extends Exchange { // "status":2 // } // - let symbol = undefined; - const responseMarket = this.safeValue (this.marketsById, order['symbol']); - if (responseMarket !== undefined) { - symbol = responseMarket['symbol']; - } else if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeInteger (order, 'create_time'); // Limit Order Request Returns: Order Price // Market Order Returns: cny amount of market order - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount', 0.0); - const filled = this.safeFloat (order, 'deal_amount', 0.0); - const av_price = this.safeFloat (order, 'avg_price'); - let cost = undefined; - if (av_price !== undefined) { - cost = filled * av_price; - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount', 0.0); + const filled = this.safeNumber (order, 'deal_amount', 0.0); + const average = this.safeNumber (order, 'avg_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'order_id'); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -90921,15 +89343,15 @@ module.exports = class lbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': this.safeValue (order, 'info', order), - 'average': undefined, - }; + 'average': average, + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -91129,14 +89551,15 @@ module.exports = class lbank extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],108:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],105:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported } = require ('./base/errors'); +const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -91240,7 +89663,7 @@ module.exports = class liquid extends Exchange { 'trading': { 'tierBased': true, 'percentage': true, - 'taker': 0.0015, + 'taker': 0.0030, 'maker': 0.0000, 'tiers': { 'perpetual': { @@ -91259,48 +89682,52 @@ module.exports = class liquid extends Exchange { [ 300000000, -0.00025 ], ], 'taker': [ - [ 0, 0.000600 ], - [ 25000, 0.000575 ], - [ 50000, 0.000550 ], - [ 100000, 0.000525 ], - [ 1000000, 0.000500 ], - [ 10000000, 0.000475 ], - [ 25000000, 0.000450 ], - [ 50000000, 0.000425 ], - [ 75000000, 0.000400 ], - [ 100000000, 0.000375 ], - [ 200000000, 0.000350 ], - [ 300000000, 0.000325 ], + [ 0, 0.00120 ], + [ 25000, 0.00115 ], + [ 50000, 0.00110 ], + [ 100000, 0.00105 ], + [ 1000000, 0.00100 ], + [ 10000000, 0.00095 ], + [ 25000000, 0.00090 ], + [ 50000000, 0.00085 ], + [ 75000000, 0.00080 ], + [ 100000000, 0.00075 ], + [ 200000000, 0.00070 ], + [ 300000000, 0.00065 ], ], }, 'spot': { 'taker': [ - [ 0, 0.0015 ], - [ 10000, 0.0015 ], - [ 20000, 0.0014 ], - [ 50000, 0.0013 ], - [ 100000, 0.0010 ], - [ 1000000, 0.0008 ], - [ 5000000, 0.0006 ], - [ 10000000, 0.0005 ], - [ 25000000, 0.0005 ], - [ 50000000, 0.00045 ], - [ 100000000, 0.0004 ], - [ 200000000, 0.0003 ], + [ 0, 0.003 ], + [ 10000, 0.0029 ], + [ 20000, 0.0028 ], + [ 50000, 0.0026 ], + [ 100000, 0.0020 ], + [ 1000000, 0.0016 ], + [ 5000000, 0.0012 ], + [ 10000000, 0.0010 ], + [ 25000000, 0.0009 ], + [ 50000000, 0.0008 ], + [ 100000000, 0.0007 ], + [ 200000000, 0.0006 ], + [ 500000000, 0.0004 ], + [ 1000000000, 0.0003 ], ], 'maker': [ [ 0, 0.0000 ], - [ 10000, 0.0015 ], - [ 20000, 0.1400 ], - [ 50000, 0.1300 ], - [ 100000, 0.0800 ], - [ 1000000, 0.0004 ], - [ 5000000, 0.00035 ], - [ 10000000, 0.00025 ], + [ 10000, 0.0020 ], + [ 20000, 0.0019 ], + [ 50000, 0.0018 ], + [ 100000, 0.0016 ], + [ 1000000, 0.0008 ], + [ 5000000, 0.0007 ], + [ 10000000, 0.0005 ], [ 25000000, 0.0000 ], [ 50000000, 0.0000 ], [ 100000000, 0.0000 ], [ 200000000, 0.0000 ], + [ 500000000, 0.0000 ], + [ 1000000000, 0.0000 ], ], }, }, @@ -91319,6 +89746,7 @@ module.exports = class liquid extends Exchange { 'less_than_order_size': InvalidOrder, 'price_too_high': InvalidOrder, 'price_too_small': InvalidOrder, // {"errors":{"order":["price_too_small"]}} + 'product_disabled': BadSymbol, // {"errors":{"order":["product_disabled"]}} }, 'commonCurrencies': { 'WIN': 'WCOIN', @@ -91368,7 +89796,7 @@ module.exports = class liquid extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': decimalPrecision, 'limits': { 'amount': { @@ -91384,7 +89812,7 @@ module.exports = class liquid extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal'), + 'min': this.safeNumber (currency, 'minimum_withdrawal'), 'max': undefined, }, }, @@ -91509,19 +89937,19 @@ module.exports = class liquid extends Exchange { let maker = this.fees['trading']['maker']; let taker = this.fees['trading']['taker']; if (type === 'swap') { - maker = this.safeFloat (market, 'maker_fee', this.fees['trading']['maker']); - taker = this.safeFloat (market, 'taker_fee', this.fees['trading']['taker']); + maker = this.safeNumber (market, 'maker_fee', this.fees['trading']['maker']); + taker = this.safeNumber (market, 'taker_fee', this.fees['trading']['taker']); } const disabled = this.safeValue (market, 'disabled', false); const active = !disabled; const baseCurrency = this.safeValue (currenciesByCode, base); const precision = { 'amount': 0.00000001, - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; let minAmount = undefined; if (baseCurrency !== undefined) { - minAmount = this.safeFloat (baseCurrency['info'], 'minimum_order_quantity'); + minAmount = this.safeNumber (baseCurrency['info'], 'minimum_order_quantity'); } const limits = { 'amount': { @@ -91603,8 +90031,8 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } for (let i = 0; i < fiat.length; i++) { @@ -91612,11 +90040,11 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -91635,7 +90063,7 @@ module.exports = class liquid extends Exchange { if (ticker['last_traded_price']) { const length = ticker['last_traded_price'].length; if (length > 0) { - last = this.safeFloat (ticker, 'last_traded_price'); + last = this.safeNumber (ticker, 'last_traded_price'); } } } @@ -91660,7 +90088,7 @@ module.exports = class liquid extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'last_price_24h'); + const open = this.safeNumber (ticker, 'last_price_24h'); if (open !== undefined && last !== undefined) { change = last - open; average = this.sum (last, open) / 2; @@ -91672,11 +90100,11 @@ module.exports = class liquid extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_market_ask'), - 'low': this.safeFloat (ticker, 'low_market_bid'), - 'bid': this.safeFloat (ticker, 'market_bid'), + 'high': this.safeNumber (ticker, 'high_market_ask'), + 'low': this.safeNumber (ticker, 'low_market_bid'), + 'bid': this.safeNumber (ticker, 'market_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'market_ask'), + 'ask': this.safeNumber (ticker, 'market_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -91686,7 +90114,7 @@ module.exports = class liquid extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'volume_24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -91732,14 +90160,11 @@ module.exports = class liquid extends Exchange { if (mySide !== undefined) { takerOrMaker = (takerSide === mySide) ? 'taker' : 'maker'; } - let cost = undefined; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -91942,9 +90367,9 @@ module.exports = class liquid extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeValue (this.markets_by_id, marketId); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'filled_quantity'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + let filled = this.safeNumber (order, 'filled_quantity'); + const price = this.safeNumber (order, 'price'); let symbol = undefined; let feeCurrency = undefined; if (market !== undefined) { @@ -91954,7 +90379,7 @@ module.exports = class liquid extends Exchange { const type = this.safeString (order, 'order_type'); let tradeCost = 0; let tradeFilled = 0; - let average = this.safeFloat (order, 'average_price'); + let average = this.safeNumber (order, 'average_price'); const trades = this.parseTrades (this.safeValue (order, 'executions', []), market, undefined, undefined, { 'order': orderId, 'type': type, @@ -92011,7 +90436,7 @@ module.exports = class liquid extends Exchange { 'trades': trades, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'order_fee'), + 'cost': this.safeNumber (order, 'order_fee'), }, 'info': order, }; @@ -92166,7 +90591,7 @@ module.exports = class liquid extends Exchange { const updated = this.safeTimestamp (transaction, 'updated_at'); const type = 'withdrawal'; const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); return { 'info': transaction, 'id': id, @@ -92267,13 +90692,14 @@ module.exports = class liquid extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],109:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],106:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -92349,6 +90775,10 @@ module.exports = class luno extends Exchange { 'quotes/{id}', 'withdrawals', 'withdrawals/{id}', + 'transfers', + // GET /api/exchange/2/listorders + // GET /api/exchange/2/orders/{id} + // GET /api/exchange/3/order ], 'post': [ 'accounts', @@ -92423,12 +90853,12 @@ module.exports = class luno extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), - 'max': this.safeFloat (market, 'max_volume'), + 'min': this.safeNumber (market, 'min_volume'), + 'max': this.safeNumber (market, 'max_volume'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -92479,20 +90909,22 @@ module.exports = class luno extends Exchange { const wallet = wallets[i]; const currencyId = this.safeString (wallet, 'asset'); const code = this.safeCurrencyCode (currencyId); - const reserved = this.safeFloat (wallet, 'reserved'); - const unconfirmed = this.safeFloat (wallet, 'unconfirmed'); - const balance = this.safeFloat (wallet, 'balance'); + const reserved = this.safeString (wallet, 'reserved'); + const unconfirmed = this.safeString (wallet, 'unconfirmed'); + const balance = this.safeString (wallet, 'balance'); + const reservedUnconfirmed = Precise.stringAdd (reserved, unconfirmed); + const balanceUnconfirmed = Precise.stringAdd (balance, unconfirmed); if (code in result) { - result[code]['used'] = this.sum (result[code]['used'], reserved, unconfirmed); - result[code]['total'] = this.sum (result[code]['total'], balance, unconfirmed); + result[code]['used'] = Precise.stringAdd (result[code]['used'], reservedUnconfirmed); + result[code]['total'] = Precise.stringAdd (result[code]['total'], balanceUnconfirmed); } else { const account = this.account (); - account['used'] = this.sum (reserved, unconfirmed); - account['total'] = this.sum (balance, unconfirmed); + account['used'] = reservedUnconfirmed; + account['total'] = balanceUnconfirmed; result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -92543,18 +90975,12 @@ module.exports = class luno extends Exchange { const side = (order['type'] === 'ASK') ? 'sell' : 'buy'; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'limit_volume'); - const quoteFee = this.safeFloat (order, 'fee_counter'); - const baseFee = this.safeFloat (order, 'fee_base'); - const filled = this.safeFloat (order, 'base'); - const cost = this.safeFloat (order, 'counter'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'limit_volume'); + const quoteFee = this.safeNumber (order, 'fee_counter'); + const baseFee = this.safeNumber (order, 'fee_base'); + const filled = this.safeNumber (order, 'base'); + const cost = this.safeNumber (order, 'counter'); const fee = { 'currency': undefined }; if (quoteFee) { fee['cost'] = quoteFee; @@ -92568,7 +90994,7 @@ module.exports = class luno extends Exchange { } } const id = this.safeString (order, 'order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -92585,12 +91011,12 @@ module.exports = class luno extends Exchange { 'amount': amount, 'filled': filled, 'cost': cost, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -92636,16 +91062,16 @@ module.exports = class luno extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -92655,7 +91081,7 @@ module.exports = class luno extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'rolling_24_hour_volume'), + 'baseVolume': this.safeNumber (ticker, 'rolling_24_hour_volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -92706,8 +91132,8 @@ module.exports = class luno extends Exchange { } else { side = trade['is_buy'] ? 'buy' : 'sell'; } - const feeBase = this.safeFloat (trade, 'fee_base'); - const feeCounter = this.safeFloat (trade, 'fee_counter'); + const feeBase = this.safeNumber (trade, 'fee_base'); + const feeCounter = this.safeNumber (trade, 'fee_counter'); let feeCurrency = undefined; let feeCost = undefined; if (feeBase !== undefined) { @@ -92732,10 +91158,10 @@ module.exports = class luno extends Exchange { 'type': undefined, 'side': side, 'takerOrMaker': takerOrMaker, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), // Does not include potential fee costs - 'cost': this.safeFloat (trade, 'counter'), + 'cost': this.safeNumber (trade, 'counter'), 'fee': { 'cost': feeCost, 'currency': feeCurrency, @@ -92782,8 +91208,8 @@ module.exports = class luno extends Exchange { const response = await this.privateGetFeeInfo (params); return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } @@ -92917,9 +91343,9 @@ module.exports = class luno extends Exchange { const timestamp = this.safeValue (entry, 'timestamp'); const currencyId = this.safeString (entry, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - const available_delta = this.safeFloat (entry, 'available_delta'); - const balance_delta = this.safeFloat (entry, 'balance_delta'); - const after = this.safeFloat (entry, 'balance'); + const available_delta = this.safeNumber (entry, 'available_delta'); + const balance_delta = this.safeNumber (entry, 'balance_delta'); + const after = this.safeNumber (entry, 'balance'); const comment = this.safeString (entry, 'description'); let before = after; let amount = 0.0; @@ -92988,12 +91414,13 @@ module.exports = class luno extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],110:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],107:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -93175,18 +91602,16 @@ module.exports = class lykke extends Exchange { const id = this.safeString2 (trade, 'id', 'Id'); const orderId = this.safeString (trade, 'OrderId'); const timestamp = this.parse8601 (this.safeString2 (trade, 'dateTime', 'DateTime')); - const price = this.safeFloat2 (trade, 'price', 'Price'); - let amount = this.safeFloat2 (trade, 'volume', 'Amount'); + const priceString = this.safeString2 (trade, 'price', 'Price'); + let amountString = this.safeString2 (trade, 'volume', 'Amount'); let side = this.safeStringLower (trade, 'action'); if (side === undefined) { - if (amount < 0) { - side = 'sell'; - } else { - side = 'buy'; - } + side = (amountString[0] === '-') ? 'sell' : 'buy'; } - amount = Math.abs (amount); - const cost = price * amount; + amountString = (amountString[0] === '-') ? amountString.slice (1) : amountString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = { 'cost': 0, // There are no fees for trading. https://www.lykke.com/wallet-fees-and-limits/ 'currency': market['quote'], @@ -93247,11 +91672,11 @@ module.exports = class lykke extends Exchange { const currencyId = this.safeString (balance, 'AssetId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Balance'); - account['used'] = this.safeFloat (balance, 'Reserved'); + account['total'] = this.safeString (balance, 'Balance'); + account['used'] = this.safeString (balance, 'Reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -93298,7 +91723,7 @@ module.exports = class lykke extends Exchange { // } // const id = this.safeString (result, 'Id'); - price = this.safeFloat (result, 'Price'); + price = this.safeNumber (result, 'Price'); return { 'id': id, 'info': result, @@ -93389,16 +91814,16 @@ module.exports = class lykke extends Exchange { if (market) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'lastPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -93409,7 +91834,7 @@ module.exports = class lykke extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume24H'), + 'quoteVolume': this.safeNumber (ticker, 'volume24H'), 'info': ticker, }; } @@ -93467,20 +91892,18 @@ module.exports = class lykke extends Exchange { } else if (('CreatedAt' in order) && (order['CreatedAt'])) { timestamp = this.parse8601 (order['CreatedAt']); } - const price = this.safeFloat (order, 'Price'); + const price = this.safeNumber (order, 'Price'); let side = undefined; - let amount = this.safeFloat (order, 'Volume'); + let amount = this.safeNumber (order, 'Volume'); if (amount < 0) { side = 'sell'; amount = Math.abs (amount); } else { side = 'buy'; } - const remaining = Math.abs (this.safeFloat (order, 'RemainingVolume')); - const filled = amount - remaining; - const cost = filled * price; + const remaining = Math.abs (this.safeNumber (order, 'RemainingVolume')); const id = this.safeString (order, 'Id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -93494,15 +91917,15 @@ module.exports = class lykke extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -93563,8 +91986,8 @@ module.exports = class lykke extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - let amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + let amount = this.safeNumber (bidask, amountKey); if (amount < 0) { amount = -amount; } @@ -93604,13 +92027,14 @@ module.exports = class lykke extends Exchange { } }; -},{"./base/Exchange":6}],111:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],108:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -93767,7 +92191,7 @@ module.exports = class mercado extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, baseId), + 'min': this.safeNumber (amountLimits, baseId), 'max': undefined, }, 'price': { @@ -93803,16 +92227,16 @@ module.exports = class mercado extends Exchange { const response = await this.publicGetCoinTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'ticker', {}); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -93822,7 +92246,7 @@ module.exports = class mercado extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -93837,15 +92261,12 @@ module.exports = class mercado extends Exchange { const id = this.safeString2 (trade, 'tid', 'operation_id'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee_rate'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee_rate'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -93902,12 +92323,12 @@ module.exports = class mercado extends Exchange { if (currencyId in balances) { const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -94014,32 +92435,31 @@ module.exports = class mercado extends Exchange { // } // const id = this.safeString (order, 'order_id'); + const order_type = this.safeString (order, 'order_type'); let side = undefined; if ('order_type' in order) { - side = (order['order_type'] === 1) ? 'buy' : 'sell'; + side = (order_type === '1') ? 'buy' : 'sell'; } const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'coin_pair'); market = this.safeMarket (marketId, market); const timestamp = this.safeTimestamp (order, 'created_timestamp'); const fee = { - 'cost': this.safeFloat (order, 'fee'), + 'cost': this.safeNumber (order, 'fee'), 'currency': market['quote'], }; - const price = this.safeFloat (order, 'limit_price'); - // price = this.safeFloat (order, 'executed_price_avg', price); - const average = this.safeFloat (order, 'executed_price_avg'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'executed_quantity'); - const remaining = amount - filled; - const cost = filled * average; + const price = this.safeNumber (order, 'limit_price'); + // price = this.safeNumber (order, 'executed_price_avg', price); + const average = this.safeNumber (order, 'executed_price_avg'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const lastTradeTimestamp = this.safeTimestamp (order, 'updated_timestamp'); const rawTrades = this.safeValue (order, 'operations', []); const trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'side': side, 'order': id, }); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -94053,15 +92473,15 @@ module.exports = class mercado extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -94119,11 +92539,11 @@ module.exports = class mercado extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -94244,13 +92664,14 @@ module.exports = class mercado extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],112:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],109:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -94319,11 +92740,11 @@ module.exports = class mixcoins extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.safeFloat (balance, 'lock'); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = this.safeString (balance, 'lock'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -94343,16 +92764,16 @@ module.exports = class mixcoins extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'result'); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -94362,7 +92783,7 @@ module.exports = class mixcoins extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -94375,14 +92796,11 @@ module.exports = class mixcoins extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -94475,7 +92893,7 @@ module.exports = class mixcoins extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],113:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],110:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -94483,6 +92901,7 @@ module.exports = class mixcoins extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -94722,7 +93141,7 @@ module.exports = class ndax extends Exchange { const name = this.safeString (currency, 'ProductFullName'); const type = this.safeString (currency, 'ProductType'); const code = this.safeCurrencyCode (this.safeString (currency, 'Product')); - const precision = this.safeFloat (currency, 'TickSize'); + const precision = this.safeNumber (currency, 'TickSize'); const isDisabled = this.safeValue (currency, 'IsDisabled'); const active = !isDisabled; result[code] = { @@ -94803,8 +93222,8 @@ module.exports = class ndax extends Exchange { const quote = this.safeCurrencyCode (this.safeString (market, 'Product2Symbol')); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'QuantityIncrement'), - 'price': this.safeFloat (market, 'PriceIncrement'), + 'amount': this.safeNumber (market, 'QuantityIncrement'), + 'price': this.safeNumber (market, 'PriceIncrement'), }; const sessionStatus = this.safeString (market, 'SessionStatus'); const isDisable = this.safeValue (market, 'IsDisable'); @@ -94822,11 +93241,11 @@ module.exports = class ndax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinimumQuantity'), + 'min': this.safeNumber (market, 'MinimumQuantity'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'MinimumPrice'), + 'min': this.safeNumber (market, 'MinimumPrice'), 'max': undefined, }, 'cost': { @@ -94947,27 +93366,27 @@ module.exports = class ndax extends Exchange { const timestamp = this.safeInteger (ticker, 'TimeStamp'); const marketId = this.safeString (ticker, 'InstrumentId'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'LastTradedPx'); - const percentage = this.safeFloat (ticker, 'Rolling24HrPxChangePercent'); - const change = this.safeFloat (ticker, 'Rolling24HrPxChange'); - const open = this.safeFloat (ticker, 'SessionOpen'); + const last = this.safeNumber (ticker, 'LastTradedPx'); + const percentage = this.safeNumber (ticker, 'Rolling24HrPxChangePercent'); + const change = this.safeNumber (ticker, 'Rolling24HrPxChange'); + const open = this.safeNumber (ticker, 'SessionOpen'); let average = undefined; if ((last !== undefined) && (change !== undefined)) { average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'Rolling24HrVolume'); - const quoteVolume = this.safeFloat (ticker, 'Rolling24HrNotional'); + const baseVolume = this.safeNumber (ticker, 'Rolling24HrVolume'); + const quoteVolume = this.safeNumber (ticker, 'Rolling24HrNotional'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'SessionHigh'), - 'low': this.safeFloat (ticker, 'SessionLow'), - 'bid': this.safeFloat (ticker, 'BestBid'), - 'bidVolume': undefined, // this.safeFloat (ticker, 'BidQty'), always shows 0 - 'ask': this.safeFloat (ticker, 'BestOffer'), - 'askVolume': undefined, // this.safeFloat (ticker, 'AskQty'), always shows 0 + 'high': this.safeNumber (ticker, 'SessionHigh'), + 'low': this.safeNumber (ticker, 'SessionLow'), + 'bid': this.safeNumber (ticker, 'BestBid'), + 'bidVolume': undefined, // this.safeNumber (ticker, 'BidQty'), always shows 0 + 'ask': this.safeNumber (ticker, 'BestOffer'), + 'askVolume': undefined, // this.safeNumber (ticker, 'AskQty'), always shows 0 'vwap': vwap, 'open': open, 'close': last, @@ -95040,11 +93459,11 @@ module.exports = class ndax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -95192,8 +93611,8 @@ module.exports = class ndax extends Exchange { // "OMSId":1 // } // - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let cost = undefined; let timestamp = undefined; let id = undefined; @@ -95204,11 +93623,8 @@ module.exports = class ndax extends Exchange { let fee = undefined; let type = undefined; if (Array.isArray (trade)) { - price = this.safeFloat (trade, 3); - amount = this.safeFloat (trade, 2); - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + priceString = this.safeString (trade, 3); + amountString = this.safeString (trade, 2); timestamp = this.safeInteger (trade, 6); id = this.safeString (trade, 0); marketId = this.safeInteger (trade, 1); @@ -95220,13 +93636,13 @@ module.exports = class ndax extends Exchange { id = this.safeString (trade, 'TradeId'); orderId = this.safeString2 (trade, 'OrderId', 'OrigOrderId'); marketId = this.safeString2 (trade, 'InstrumentId', 'Instrument'); - price = this.safeFloat (trade, 'Price'); - amount = this.safeFloat (trade, 'Quantity'); - cost = this.safeFloat2 (trade, 'Value', 'GrossValueExecuted'); + priceString = this.safeString (trade, 'Price'); + amountString = this.safeString (trade, 'Quantity'); + cost = this.safeNumber2 (trade, 'Value', 'GrossValueExecuted'); takerOrMaker = this.safeStringLower (trade, 'MakerTaker'); side = this.safeStringLower (trade, 'Side'); type = this.safeStringLower (trade, 'OrderType'); - const feeCost = this.safeFloat (trade, 'Fee'); + const feeCost = this.safeNumber (trade, 'Fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'FeeProductId'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -95236,6 +93652,11 @@ module.exports = class ndax extends Exchange { }; } } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const symbol = this.safeSymbol (marketId, market); return { 'info': trade, @@ -95350,11 +93771,11 @@ module.exports = class ndax extends Exchange { const currencyId = this.safeString (balance, 'ProductId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Amount'); - account['used'] = this.safeFloat (balance, 'Hold'); + account['total'] = this.safeString (balance, 'Amount'); + account['used'] = this.safeString (balance, 'Hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseLedgerEntryType (type) { @@ -95400,8 +93821,8 @@ module.exports = class ndax extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'ReferenceType')); const currencyId = this.safeString (item, 'ProductId'); const code = this.safeCurrencyCode (currencyId, currency); - const credit = this.safeFloat (item, 'CR'); - const debit = this.safeFloat (item, 'DR'); + const credit = this.safeNumber (item, 'CR'); + const debit = this.safeNumber (item, 'DR'); let amount = undefined; let direction = undefined; if (credit > 0) { @@ -95413,7 +93834,7 @@ module.exports = class ndax extends Exchange { } const timestamp = this.safeInteger (item, 'TimeStamp'); let before = undefined; - const after = this.safeFloat (item, 'Balance'); + const after = this.safeNumber (item, 'Balance'); if (direction === 'out') { before = this.sum (after, amount); } else if (direction === 'in') { @@ -95561,36 +93982,26 @@ module.exports = class ndax extends Exchange { // const id = this.safeString2 (order, 'ReplacementOrderId', 'OrderId'); const timestamp = this.safeInteger (order, 'ReceiveTime'); - let lastTradeTimestamp = undefined; + const lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); const marketId = this.safeString (order, 'Instrument'); const symbol = this.safeSymbol (marketId, market); const side = this.safeStringLower (order, 'Side'); const type = this.safeStringLower (order, 'OrderType'); const clientOrderId = this.safeString2 (order, 'ReplacementClOrdId', 'ClientOrderId'); - let price = this.safeFloat (order, 'Price', 0.0); + let price = this.safeNumber (order, 'Price', 0.0); price = (price > 0.0) ? price : undefined; - const amount = this.safeFloat (order, 'OrigQuantity'); - const filled = this.safeFloat (order, 'QuantityExecuted'); - const cost = this.safeFloat (order, 'GrossValueExecuted'); - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (filled > 0) { - lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); - average = this.safeFloat (order, 'AvgPrice', 0.0); - average = (average > 0) ? average : undefined; - } - } - let stopPrice = this.safeFloat (order, 'StopPrice', 0.0); + const amount = this.safeNumber (order, 'OrigQuantity'); + const filled = this.safeNumber (order, 'QuantityExecuted'); + const cost = this.safeNumber (order, 'GrossValueExecuted'); + let average = this.safeNumber (order, 'AvgPrice', 0.0); + average = (average > 0) ? average : undefined; + let stopPrice = this.safeNumber (order, 'StopPrice', 0.0); stopPrice = (stopPrice > 0.0) ? stopPrice : undefined; const timeInForce = undefined; const status = this.parseOrderStatus (this.safeString (order, 'OrderState')); const fee = undefined; const trades = undefined; - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -95609,10 +94020,10 @@ module.exports = class ndax extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -96410,8 +94821,8 @@ module.exports = class ndax extends Exchange { } const addressTo = address; const status = this.parseTransactionStatusByType (this.safeString (transaction, 'TicketStatus'), type); - const amount = this.safeFloat (transaction, 'Amount'); - const feeCost = this.safeFloat (transaction, 'FeeAmount'); + const amount = this.safeNumber (transaction, 'Amount'); + const feeCost = this.safeNumber (transaction, 'FeeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -96492,7 +94903,7 @@ module.exports = class ndax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],114:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],111:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -96500,6 +94911,7 @@ module.exports = class ndax extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, BadRequest, CancelPending, OrderNotFound, InsufficientFunds, RateLimitExceeded, InvalidOrder, AccountSuspended, BadSymbol, OnMaintenance } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -96692,7 +95104,7 @@ module.exports = class novadax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -96700,7 +95112,7 @@ module.exports = class novadax extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderValue'), + 'min': this.safeNumber (market, 'minOrderValue'), 'max': undefined, }, }; @@ -96742,8 +95154,8 @@ module.exports = class novadax extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const open = this.safeFloat (ticker, 'open24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'open24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let percentage = undefined; let change = undefined; let average = undefined; @@ -96752,18 +95164,18 @@ module.exports = class novadax extends Exchange { percentage = change / open * 100; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'baseVolume24h'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume24h'); + const baseVolume = this.safeNumber (ticker, 'baseVolume24h'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -96919,11 +95331,13 @@ module.exports = class novadax extends Exchange { const orderId = this.safeString (trade, 'orderId'); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeStringLower (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - cost = amount * price; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'volume'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); @@ -96935,7 +95349,7 @@ module.exports = class novadax extends Exchange { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { - 'cost': this.safeFloat (parts, 0), + 'cost': this.safeNumber (parts, 0), 'currency': feeCurrencyCode, }; } @@ -97043,11 +95457,11 @@ module.exports = class novadax extends Exchange { const volumeField = this.safeString (options, 'volume', 'amount'); // or vol return [ this.safeTimestamp (ohlcv, 'score'), - this.safeFloat (ohlcv, 'openPrice'), - this.safeFloat (ohlcv, 'highPrice'), - this.safeFloat (ohlcv, 'lowPrice'), - this.safeFloat (ohlcv, 'closePrice'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'openPrice'), + this.safeNumber (ohlcv, 'highPrice'), + this.safeNumber (ohlcv, 'lowPrice'), + this.safeNumber (ohlcv, 'closePrice'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -97075,12 +95489,12 @@ module.exports = class novadax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'available'); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); + account['total'] = this.safeString (balance, 'available'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -97103,7 +95517,7 @@ module.exports = class novadax extends Exchange { if (uppercaseSide === 'SELL') { request['amount'] = this.amountToPrecision (symbol, amount); } else if (uppercaseSide === 'BUY') { - let value = this.safeFloat (params, 'value'); + let value = this.safeNumber (params, 'value'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -97333,21 +95747,17 @@ module.exports = class novadax extends Exchange { // } // const id = this.safeString (order, 'id'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'filledValue'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'filledValue'); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeInteger (order, 'timestamp'); - const average = this.safeFloat (order, 'averagePrice'); - const filled = this.safeFloat (order, 'filledAmount'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } + const average = this.safeNumber (order, 'averagePrice'); + const filled = this.safeNumber (order, 'filledAmount'); let fee = undefined; - const feeCost = this.safeFloat (order, 'filledFee'); + const feeCost = this.safeNumber (order, 'filledFee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -97356,7 +95766,7 @@ module.exports = class novadax extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -97374,11 +95784,11 @@ module.exports = class novadax extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async withdraw (code, amount, address, tag = undefined, params = {}) { @@ -97541,7 +95951,7 @@ module.exports = class novadax extends Exchange { } else if (type === 'COIN_OUT') { type = 'withdraw'; } - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'addressTag'); const txid = this.safeString (transaction, 'txHash'); @@ -97683,7 +96093,7 @@ module.exports = class novadax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],115:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],112:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -97833,10 +96243,10 @@ module.exports = class oceanex extends Exchange { 'active': true, 'info': market, 'precision': { - 'amount': this.safeValue (market, 'amount_precision'), - 'price': this.safeValue (market, 'price_precision'), - 'base': this.safeValue (market, 'ask_precision'), - 'quote': this.safeValue (market, 'bid_precision'), + 'amount': this.safeInteger (market, 'amount_precision'), + 'price': this.safeInteger (market, 'price_precision'), + 'base': this.safeInteger (market, 'ask_precision'), + 'quote': this.safeInteger (market, 'bid_precision'), }, 'limits': { 'amount': { @@ -97848,7 +96258,7 @@ module.exports = class oceanex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeValue (market, 'minimum_trading_amount'), + 'min': this.safeNumber (market, 'minimum_trading_amount'), 'max': undefined, }, }, @@ -97942,21 +96352,21 @@ module.exports = class oceanex extends Exchange { 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (ticker, 'last'), - 'last': this.safeFloat (ticker, 'last'), + 'close': this.safeNumber (ticker, 'last'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -98081,8 +96491,8 @@ module.exports = class oceanex extends Exchange { 'type': 'limit', 'takerOrMaker': undefined, 'side': side, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), 'cost': undefined, 'fee': undefined, }; @@ -98109,8 +96519,8 @@ module.exports = class oceanex extends Exchange { result[symbol] = { 'info': group, 'symbol': symbol, - 'maker': this.safeFloat (maker, 'value'), - 'taker': this.safeFloat (taker, 'value'), + 'maker': this.safeNumber (maker, 'value'), + 'taker': this.safeNumber (taker, 'value'), }; } return result; @@ -98132,11 +96542,11 @@ module.exports = class oceanex extends Exchange { const currencyId = this.safeValue (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -98244,12 +96654,12 @@ module.exports = class oceanex extends Exchange { // const status = this.parseOrderStatus (this.safeValue (order, 'state')); const marketId = this.safeString2 (order, 'market', 'market_id'); - const symbol = this.safeSymbol (marketId); + const symbol = this.safeSymbol (marketId, market); let timestamp = this.safeTimestamp (order, 'created_on'); if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'created_at')); } - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, @@ -98261,17 +96671,17 @@ module.exports = class oceanex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeValue (order, 'side'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_price'), - 'amount': this.safeFloat (order, 'volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'filled': this.safeFloat (order, 'executed_volume'), + 'average': this.safeNumber (order, 'avg_price'), + 'amount': this.safeNumber (order, 'volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'filled': this.safeNumber (order, 'executed_volume'), 'status': status, 'cost': undefined, 'trades': undefined, 'fee': undefined, - }; + }); } parseOrderStatus (status) { @@ -98364,12 +96774,12 @@ module.exports = class oceanex extends Exchange { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['codes'], errorCode, feedback); this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - throw new ExchangeError (response); + throw new ExchangeError (feedback); } } }; -},{"./base/Exchange":6,"./base/errors":8}],116:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],113:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -98406,7 +96816,7 @@ module.exports = class okcoin extends okex { } }; -},{"./okex.js":117}],117:[function(require,module,exports){ +},{"./okex.js":114}],114:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -98414,6 +96824,7 @@ module.exports = class okcoin extends okex { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -99207,7 +97618,7 @@ module.exports = class okex extends Exchange { let option = false; let baseId = this.safeString (market, 'base_currency'); let quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { if ('option_type' in market) { marketType = 'option'; @@ -99233,12 +97644,12 @@ module.exports = class okex extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = spot ? (base + '/' + quote) : id; - const lotSize = this.safeFloat2 (market, 'lot_size', 'trade_increment'); + const lotSize = this.safeNumber2 (market, 'lot_size', 'trade_increment'); const precision = { - 'amount': this.safeFloat (market, 'size_increment', lotSize), - 'price': this.safeFloat (market, 'tick_size'), + 'amount': this.safeNumber (market, 'size_increment', lotSize), + 'price': this.safeNumber (market, 'tick_size'), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const active = true; const fees = this.safeValue2 (this.fees, marketType, 'trading', {}); return this.extend (fees, { @@ -99413,7 +97824,7 @@ module.exports = class okex extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal'), + 'min': this.safeNumber (currency, 'min_withdrawal'), 'max': undefined, }, }, @@ -99488,18 +97899,18 @@ module.exports = class okex extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open_24h'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open_24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_24h'), - 'low': this.safeFloat (ticker, 'low_24h'), - 'bid': this.safeFloat (ticker, 'best_bid'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (ticker, 'best_ask'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber (ticker, 'high_24h'), + 'low': this.safeNumber (ticker, 'low_24h'), + 'bid': this.safeNumber (ticker, 'best_bid'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (ticker, 'best_ask'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': undefined, 'open': open, 'close': last, @@ -99508,8 +97919,8 @@ module.exports = class okex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'base_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'quote_volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'base_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'quote_volume_24h'), 'info': ticker, }; } @@ -99646,9 +98057,12 @@ module.exports = class okex extends Exchange { quote = market['quote']; } const timestamp = this.parse8601 (this.safeString2 (trade, 'timestamp', 'created_at')); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'size', 'qty'); - amount = this.safeFloat (trade, 'order_qty', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'size', 'qty'); + amountString = this.safeString (trade, 'order_qty', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -99656,13 +98070,7 @@ module.exports = class okex extends Exchange { takerOrMaker = 'taker'; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -99771,22 +98179,22 @@ module.exports = class okex extends Exchange { } return [ timestamp, // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets ]; } else { return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, 'volume'), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, 'volume'), // Base Volume ]; } } @@ -99932,9 +98340,9 @@ module.exports = class okex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeNumber (balance, 'balance'); + account['used'] = this.safeNumber (balance, 'hold'); + account['free'] = this.safeNumber (balance, 'available'); result[code] = account; } return this.parseBalance (result); @@ -100004,9 +98412,9 @@ module.exports = class okex extends Exchange { const currencyId = parts[1]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (marketBalance, 'balance'); - account['used'] = this.safeFloat (marketBalance, 'hold'); - account['free'] = this.safeFloat (marketBalance, 'available'); + account['total'] = this.safeNumber (marketBalance, 'balance'); + account['used'] = this.safeNumber (marketBalance, 'hold'); + account['free'] = this.safeNumber (marketBalance, 'available'); accounts[code] = account; } else { throw new NotSupported (this.id + ' margin balance response format has changed!'); @@ -100059,29 +98467,29 @@ module.exports = class okex extends Exchange { const code = this.safeCurrencyCode (id); const balance = this.safeValue (info, id, {}); const account = this.account (); - const totalAvailBalance = this.safeFloat (balance, 'total_avail_balance'); + const totalAvailBalance = this.safeNumber (balance, 'total_avail_balance'); if (this.safeString (balance, 'margin_mode') === 'fixed') { const contracts = this.safeValue (balance, 'contracts', []); let free = totalAvailBalance; for (let i = 0; i < contracts.length; i++) { const contract = contracts[i]; - const fixedBalance = this.safeFloat (contract, 'fixed_balance'); - const realizedPnl = this.safeFloat (contract, 'realized_pnl'); - const marginFrozen = this.safeFloat (contract, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (contract, 'margin_for_unfilled'); + const fixedBalance = this.safeNumber (contract, 'fixed_balance'); + const realizedPnl = this.safeNumber (contract, 'realized_pnl'); + const marginFrozen = this.safeNumber (contract, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (contract, 'margin_for_unfilled'); const margin = this.sum (fixedBalance, realizedPnl) - marginFrozen - marginForUnfilled; free = this.sum (free, margin); } account['free'] = free; } else { - const realizedPnl = this.safeFloat (balance, 'realized_pnl'); - const unrealizedPnl = this.safeFloat (balance, 'unrealized_pnl'); - const marginFrozen = this.safeFloat (balance, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (balance, 'margin_for_unfilled'); + const realizedPnl = this.safeNumber (balance, 'realized_pnl'); + const unrealizedPnl = this.safeNumber (balance, 'unrealized_pnl'); + const marginFrozen = this.safeNumber (balance, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (balance, 'margin_for_unfilled'); account['free'] = this.sum (totalAvailBalance, realizedPnl, unrealizedPnl) - marginFrozen - marginForUnfilled; } // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); + account['total'] = this.safeNumber (balance, 'equity'); result[code] = account; } return this.parseBalance (result); @@ -100119,8 +98527,8 @@ module.exports = class okex extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeNumber (balance, 'equity'); + account['free'] = this.safeNumber (balance, 'total_avail_balance'); result[symbol] = account; } return this.parseBalance (result); @@ -100324,7 +98732,7 @@ module.exports = class okex extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -100534,8 +98942,8 @@ module.exports = class okex extends Exchange { symbol = market['symbol']; } } - let amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat2 (order, 'filled_size', 'filled_qty'); + let amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber2 (order, 'filled_size', 'filled_qty'); let remaining = undefined; if (amount !== undefined) { if (filled !== undefined) { @@ -100546,9 +98954,9 @@ module.exports = class okex extends Exchange { if (type === 'market') { remaining = 0; } - let cost = this.safeFloat2 (order, 'filled_notional', 'funds'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); + let cost = this.safeNumber2 (order, 'filled_notional', 'funds'); + const price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'price_avg'); if (cost === undefined) { if (filled !== undefined && average !== undefined) { cost = average * filled; @@ -100559,7 +98967,7 @@ module.exports = class okex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'state')); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -100572,7 +98980,7 @@ module.exports = class okex extends Exchange { if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) { clientOrderId = undefined; // fix empty clientOrderId string } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); return { 'info': order, 'id': id, @@ -100816,16 +99224,6 @@ module.exports = class okex extends Exchange { return await this.fetchOrdersByState ('7', symbol, since, limit, params); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -100853,7 +99251,8 @@ module.exports = class okex extends Exchange { async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); - const currency = this.currency (code); + const parts = code.split ('-'); + const currency = this.currency (parts[0]); const request = { 'currency': currency['id'], }; @@ -100866,8 +99265,8 @@ module.exports = class okex extends Exchange { // } // ] // - const addresses = this.parseDepositAddresses (response); - const address = this.safeValue (addresses, code); + const addressesByCode = this.parseDepositAddresses (response); + const address = this.safeValue (addressesByCode, code); if (address === undefined) { throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first'); } @@ -101042,7 +99441,7 @@ module.exports = class okex extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const txid = this.safeString (transaction, 'txid'); const timestamp = this.parse8601 (this.safeString (transaction, 'timestamp')); @@ -101105,19 +99504,19 @@ module.exports = class okex extends Exchange { let feeCurrencyId = undefined; if (receivedCurrencyId === quoteId) { side = this.safeString (otherTrade, 'side'); - amount = this.safeFloat (otherTrade, 'size'); - cost = this.safeFloat (userTrade, 'size'); + amount = this.safeNumber (otherTrade, 'size'); + cost = this.safeNumber (userTrade, 'size'); feeCurrencyId = this.safeString (otherTrade, 'currency'); } else { side = this.safeString (userTrade, 'side'); - amount = this.safeFloat (userTrade, 'size'); - cost = this.safeFloat (otherTrade, 'size'); + amount = this.safeNumber (userTrade, 'size'); + cost = this.safeNumber (otherTrade, 'size'); feeCurrencyId = this.safeString (userTrade, 'currency'); } const id = this.safeString (userTrade, 'trade_id'); - const price = this.safeFloat (userTrade, 'price'); - const feeCostFirst = this.safeFloat (otherTrade, 'fee'); - const feeCostSecond = this.safeFloat (userTrade, 'fee'); + const price = this.safeNumber (userTrade, 'price'); + const feeCostFirst = this.safeNumber (otherTrade, 'fee'); + const feeCostSecond = this.safeNumber (userTrade, 'fee'); const feeCurrencyCodeFirst = this.safeCurrencyCode (this.safeString (otherTrade, 'currency')); const feeCurrencyCodeSecond = this.safeCurrencyCode (this.safeString (userTrade, 'currency')); let fee = undefined; @@ -101549,7 +99948,7 @@ module.exports = class okex extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); let method = undefined; const defaultType = this.safeString2 (this.options, 'fetchPositions', 'defaultType'); @@ -101931,14 +100330,14 @@ module.exports = class okex extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'timestamp')); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; const marketId = this.safeString (item, 'instrument_id'); let symbol = undefined; @@ -102048,13 +100447,14 @@ module.exports = class okex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],118:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],115:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -102147,12 +100547,12 @@ module.exports = class paymium extends Exchange { if (free in response) { const account = this.account (); const used = 'locked_' + currencyId; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -102171,30 +100571,30 @@ module.exports = class paymium extends Exchange { }; const ticker = await this.publicGetDataCurrencyTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'at'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'price'); + const last = this.safeNumber (ticker, 'price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'variation'), + 'percentage': this.safeNumber (ticker, 'variation'), 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, @@ -102210,15 +100610,12 @@ module.exports = class paymium extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); + const priceString = this.safeString (trade, 'price'); const amountField = 'traded_' + market['base'].toLowerCase (); - const amount = this.safeFloat (trade, amountField); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const amountString = this.safeString (trade, amountField); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -102313,7 +100710,7 @@ module.exports = class paymium extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],119:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],116:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -102621,13 +101018,13 @@ module.exports = class phemex extends Exchange { }); } - parseSafeFloat (value = undefined) { + parseSafeNumber (value = undefined) { if (value === undefined) { return value; } value = value.replace (',', ''); const parts = value.split (' '); - return this.safeFloat (parts, 0); + return this.safeNumber (parts, 0); } parseSwapMarket (market) { @@ -102651,7 +101048,9 @@ module.exports = class phemex extends Exchange { // "minPriceEp":5000, // "maxPriceEp":10000000000, // "maxOrderQty":1000000, - // "type":"Perpetual" + // "type":"Perpetual", + // "status":"Listed", + // "tipOrderQty":1000000, // "steps":"50", // "riskLimits":[ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000}, @@ -102676,7 +101075,7 @@ module.exports = class phemex extends Exchange { // } // const id = this.safeString (market, 'symbol'); - const baseId = this.safeString (market, 'baseCurrency', 'contractUnderlyingAssets'); + const baseId = this.safeString2 (market, 'baseCurrency', 'contractUnderlyingAssets'); const quoteId = this.safeString (market, 'quoteCurrency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); @@ -102693,16 +101092,16 @@ module.exports = class phemex extends Exchange { } const linear = !inverse; const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const priceScale = this.safeInteger (market, 'priceScale'); const ratioScale = this.safeInteger (market, 'ratioScale'); const valueScale = this.safeInteger (market, 'valueScale'); - const minPriceEp = this.safeFloat (market, 'minPriceEp'); - const maxPriceEp = this.safeFloat (market, 'maxPriceEp'); - const makerFeeRateEr = this.safeFloat (market, 'makerFeeRateEr'); - const takerFeeRateEr = this.safeFloat (market, 'takerFeeRateEr'); + const minPriceEp = this.safeNumber (market, 'minPriceEp'); + const maxPriceEp = this.safeNumber (market, 'maxPriceEp'); + const makerFeeRateEr = this.safeNumber (market, 'makerFeeRateEr'); + const takerFeeRateEr = this.safeNumber (market, 'takerFeeRateEr'); if (makerFeeRateEr !== undefined) { maker = this.fromEn (makerFeeRateEr, ratioScale, 0.00000001); } @@ -102720,10 +101119,11 @@ module.exports = class phemex extends Exchange { }, 'cost': { 'min': undefined, - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderQty')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderQty')), }, }; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -102772,7 +101172,9 @@ module.exports = class phemex extends Exchange { // "defaultMakerFee":"0.001", // "defaultMakerFeeEr":100000, // "baseQtyPrecision":6, - // "quoteQtyPrecision":2 + // "quoteQtyPrecision":2, + // "status":"Listed", + // "tipOrderQty":20 // } // const type = this.safeStringLower (market, 'type'); @@ -102783,30 +101185,31 @@ module.exports = class phemex extends Exchange { const inverse = undefined; const spot = true; const swap = false; - const taker = this.safeFloat (market, 'defaultTakerFee'); - const maker = this.safeFloat (market, 'defaultMakerFee'); + const taker = this.safeNumber (market, 'defaultTakerFee'); + const maker = this.safeNumber (market, 'defaultMakerFee'); const precision = { - 'amount': this.parseSafeFloat (this.safeString (market, 'baseTickSize')), - 'price': this.parseSafeFloat (this.safeString (market, 'quoteTickSize')), + 'amount': this.parseSafeNumber (this.safeString (market, 'baseTickSize')), + 'price': this.parseSafeNumber (this.safeString (market, 'quoteTickSize')), }; const limits = { 'amount': { 'min': precision['amount'], - 'max': this.parseSafeFloat (this.safeString (market, 'maxBaseOrderSize')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxBaseOrderSize')), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.parseSafeFloat (this.safeString (market, 'minOrderValue')), - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderValue')), + 'min': this.parseSafeNumber (this.safeString (market, 'minOrderValue')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderValue')), }, }; const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -102996,8 +101399,8 @@ module.exports = class phemex extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const valueScale = this.safeInteger (currency, 'valueScale'); - const minValueEv = this.safeFloat (currency, 'minValueEv'); - const maxValueEv = this.safeFloat (currency, 'maxValueEv'); + const minValueEv = this.safeNumber (currency, 'minValueEv'); + const maxValueEv = this.safeNumber (currency, 'maxValueEv'); let minAmount = undefined; let maxAmount = undefined; let precision = undefined; @@ -103047,12 +101450,12 @@ module.exports = class phemex extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - let amount = this.safeFloat (bidask, amountKey); + let amount = this.safeNumber (bidask, amountKey); if (market['spot']) { amount = this.fromEv (amount, market); } return [ - this.fromEp (this.safeFloat (bidask, priceKey), market), + this.fromEp (this.safeNumber (bidask, priceKey), market), amount, ]; } @@ -103186,16 +101589,16 @@ module.exports = class phemex extends Exchange { // let baseVolume = undefined; if ((market !== undefined) && market['spot']) { - baseVolume = this.fromEv (this.safeFloat (ohlcv, 7), market); + baseVolume = this.fromEv (this.safeNumber (ohlcv, 7), market); } else { baseVolume = this.safeInteger (ohlcv, 7); } return [ this.safeTimestamp (ohlcv, 0), - this.fromEp (this.safeFloat (ohlcv, 3), market), - this.fromEp (this.safeFloat (ohlcv, 4), market), - this.fromEp (this.safeFloat (ohlcv, 5), market), - this.fromEp (this.safeFloat (ohlcv, 6), market), + this.fromEp (this.safeNumber (ohlcv, 3), market), + this.fromEp (this.safeNumber (ohlcv, 4), market), + this.fromEp (this.safeNumber (ohlcv, 5), market), + this.fromEp (this.safeNumber (ohlcv, 6), market), baseVolume, ]; } @@ -103288,11 +101691,11 @@ module.exports = class phemex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.000001); - const last = this.fromEp (this.safeFloat (ticker, 'lastEp'), market); - const quoteVolume = this.fromEp (this.safeFloat (ticker, 'turnoverEv'), market); - let baseVolume = this.safeFloat (ticker, 'volume'); + const last = this.fromEp (this.safeNumber (ticker, 'lastEp'), market); + const quoteVolume = this.fromEp (this.safeNumber (ticker, 'turnoverEv'), market); + let baseVolume = this.safeNumber (ticker, 'volume'); if (baseVolume === undefined) { - baseVolume = this.fromEv (this.safeFloat (ticker, 'volumeEv')); + baseVolume = this.fromEv (this.safeNumber (ticker, 'volumeEv')); } let vwap = undefined; if ((market !== undefined) && (market['spot'])) { @@ -103301,7 +101704,7 @@ module.exports = class phemex extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.fromEp (this.safeFloat (ticker, 'openEp'), market); + const open = this.fromEp (this.safeNumber (ticker, 'openEp'), market); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -103313,11 +101716,11 @@ module.exports = class phemex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.fromEp (this.safeFloat (ticker, 'highEp'), market), - 'low': this.fromEp (this.safeFloat (ticker, 'lowEp'), market), - 'bid': this.fromEp (this.safeFloat (ticker, 'bidEp'), market), + 'high': this.fromEp (this.safeNumber (ticker, 'highEp'), market), + 'low': this.fromEp (this.safeNumber (ticker, 'lowEp'), market), + 'bid': this.fromEp (this.safeNumber (ticker, 'bidEp'), market), 'bidVolume': undefined, - 'ask': this.fromEp (this.safeFloat (ticker, 'askEp'), market), + 'ask': this.fromEp (this.safeNumber (ticker, 'askEp'), market), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -103508,8 +101911,8 @@ module.exports = class phemex extends Exchange { id = this.safeString (trade, tradeLength - 4); } side = this.safeStringLower (trade, tradeLength - 3); - price = this.fromEp (this.safeFloat (trade, tradeLength - 2), market); - amount = this.fromEv (this.safeFloat (trade, tradeLength - 1), market); + price = this.fromEp (this.safeNumber (trade, tradeLength - 2), market); + amount = this.fromEv (this.safeNumber (trade, tradeLength - 1), market); if (market['spot']) { if ((price !== undefined) && (amount !== undefined)) { cost = price * amount; @@ -103525,14 +101928,14 @@ module.exports = class phemex extends Exchange { if (execStatus === 'MakerFill') { takerOrMaker = 'maker'; } - price = this.fromEp (this.safeFloat (trade, 'execPriceEp'), market); - amount = this.fromEv (this.safeFloat (trade, 'execBaseQtyEv'), market); - amount = this.safeFloat (trade, 'execQty', amount); - cost = this.fromEv (this.safeFloat2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); - const feeCost = this.fromEv (this.safeFloat (trade, 'execFeeEv'), market); + price = this.fromEp (this.safeNumber (trade, 'execPriceEp'), market); + amount = this.fromEv (this.safeNumber (trade, 'execBaseQtyEv'), market); + amount = this.safeNumber (trade, 'execQty', amount); + cost = this.fromEv (this.safeNumber2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); + const feeCost = this.fromEv (this.safeNumber (trade, 'execFeeEv'), market); if (feeCost !== undefined) { let feeRate = undefined; - let feeRateEr = this.safeFloat (trade, 'feeRateEr'); + let feeRateEr = this.safeNumber (trade, 'feeRateEr'); if (feeRateEr < 0) { feeRateEr = Math.abs (feeRateEr); feeRate = this.fromEr (feeRateEr, market); @@ -103608,9 +102011,9 @@ module.exports = class phemex extends Exchange { const currency = this.safeValue (this.currencies, code, {}); const scale = this.safeInteger (currency, 'valueScale', 8); const account = this.account (); - const balanceEv = this.safeFloat (balance, 'balanceEv'); - const lockedTradingBalanceEv = this.safeFloat (balance, 'lockedTradingBalanceEv'); - const lockedWithdrawEv = this.safeFloat (balance, 'lockedWithdrawEv'); + const balanceEv = this.safeNumber (balance, 'balanceEv'); + const lockedTradingBalanceEv = this.safeNumber (balance, 'lockedTradingBalanceEv'); + const lockedWithdrawEv = this.safeNumber (balance, 'lockedWithdrawEv'); const total = this.fromEn (balanceEv, scale, scale, DECIMAL_PLACES); const lockedTradingBalance = this.fromEn (lockedTradingBalanceEv, scale, scale, DECIMAL_PLACES); const lockedWithdraw = this.fromEn (lockedWithdrawEv, scale, scale, DECIMAL_PLACES); @@ -103704,8 +102107,8 @@ module.exports = class phemex extends Exchange { const code = this.safeCurrencyCode (currencyId); const currency = this.currency (code); const account = this.account (); - const accountBalanceEv = this.safeFloat (balance, 'accountBalanceEv'); - const totalUsedBalanceEv = this.safeFloat (balance, 'totalUsedBalanceEv'); + const accountBalanceEv = this.safeNumber (balance, 'accountBalanceEv'); + const totalUsedBalanceEv = this.safeNumber (balance, 'totalUsedBalanceEv'); const valueScale = this.safeInteger (currency, 'valueScale', 8); account['total'] = this.fromEn (accountBalanceEv, valueScale, valueScale, DECIMAL_PLACES); account['used'] = this.fromEn (totalUsedBalanceEv, valueScale, valueScale, DECIMAL_PLACES); @@ -103937,21 +102340,21 @@ module.exports = class phemex extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let price = this.fromEp (this.safeFloat (order, 'priceEp'), market); + let price = this.fromEp (this.safeNumber (order, 'priceEp'), market); if (price === 0) { price = undefined; } - const amount = this.fromEv (this.safeFloat (order, 'baseQtyEv'), market); - const remaining = this.fromEv (this.safeFloat (order, 'leavesBaseQtyEv'), market); - let filled = this.fromEv (this.safeFloat (order, 'cumBaseQtyEv'), market); - const cost = this.fromEv (this.safeFloat (order, 'quoteQtyEv'), market); - const average = this.fromEp (this.safeFloat (order, 'avgPriceEp'), market); + const amount = this.fromEv (this.safeNumber (order, 'baseQtyEv'), market); + const remaining = this.fromEv (this.safeNumber (order, 'leavesBaseQtyEv'), market); + let filled = this.fromEv (this.safeNumber (order, 'cumBaseQtyEv'), market); + const cost = this.fromEv (this.safeNumber (order, 'quoteQtyEv'), market); + const average = this.fromEp (this.safeNumber (order, 'avgPriceEp'), market); const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'ordType')); const timestamp = this.safeIntegerProduct2 (order, 'actionTimeNs', 'createTimeNs', 0.000001); let fee = undefined; - const feeCost = this.fromEv (this.safeFloat (order, 'cumFeeEv'), market); + const feeCost = this.fromEv (this.safeNumber (order, 'cumFeeEv'), market); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -103964,7 +102367,7 @@ module.exports = class phemex extends Exchange { } } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.fromEp (this.safeFloat (order, 'stopPxEp', market)); + const stopPrice = this.fromEp (this.safeNumber (order, 'stopPxEp', market)); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -104037,18 +102440,18 @@ module.exports = class phemex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'orderType')); - const price = this.fromEp (this.safeFloat (order, 'priceEp'), market); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); + const price = this.fromEp (this.safeNumber (order, 'priceEp'), market); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); const timestamp = this.safeIntegerProduct (order, 'actionTimeNs', 0.000001); - const cost = this.safeFloat (order, 'cumValue'); + const cost = this.safeNumber (order, 'cumValue'); let lastTradeTimestamp = this.safeIntegerProduct (order, 'transactTimeNs', 0.000001); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -104123,7 +102526,7 @@ module.exports = class phemex extends Exchange { } request['qtyType'] = qtyType; if (qtyType === 'ByQuote') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); params = this.omit (params, 'cost'); if (this.options['createOrderByQuoteRequiresPrice']) { if (price !== undefined) { @@ -104143,7 +102546,7 @@ module.exports = class phemex extends Exchange { if (type === 'Limit') { request['priceEp'] = this.toEp (price, market); } - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice !== undefined) { request['stopPxEp'] = this.toEp (stopPrice, market); } @@ -104651,7 +103054,7 @@ module.exports = class phemex extends Exchange { const code = currency['code']; const timestamp = this.safeInteger2 (transaction, 'createdAt', 'submitedAt'); let type = this.safeStringLower (transaction, 'type'); - const feeCost = this.fromEn (this.safeFloat (transaction, 'feeEv'), currency['valueScale'], currency['precision']); + const feeCost = this.fromEn (this.safeNumber (transaction, 'feeEv'), currency['valueScale'], currency['precision']); let fee = undefined; if (feeCost !== undefined) { type = 'withdrawal'; @@ -104661,7 +103064,7 @@ module.exports = class phemex extends Exchange { }; } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.fromEn (this.safeFloat (transaction, 'amountEv'), currency['valueScale'], currency['precision']); + const amount = this.fromEn (this.safeNumber (transaction, 'amountEv'), currency['valueScale'], currency['precision']); return { 'info': transaction, 'id': id, @@ -104683,7 +103086,7 @@ module.exports = class phemex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.safeString (params, 'code'); const request = {}; @@ -104836,13 +103239,14 @@ module.exports = class phemex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],120:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],117:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -104952,6 +103356,7 @@ module.exports = class poloniex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', // starting from Jan 8 2020 'maker': 0.0009, 'taker': 0.0009, @@ -105046,24 +103451,6 @@ module.exports = class poloniex extends Exchange { }); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - parseOHLCV (ohlcv, market = undefined) { // // { @@ -105079,11 +103466,11 @@ module.exports = class poloniex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'date'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'quoteVolume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'quoteVolume'), ]; } @@ -105176,11 +103563,11 @@ module.exports = class poloniex extends Exchange { const balance = this.safeValue (response, currencyId, {}); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onOrders'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFees (params = {}) { @@ -105198,8 +103585,8 @@ module.exports = class poloniex extends Exchange { // return { 'info': fees, - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), 'withdraw': {}, 'deposit': {}, }; @@ -105257,8 +103644,8 @@ module.exports = class poloniex extends Exchange { let open = undefined; let change = undefined; let average = undefined; - const last = this.safeFloat (ticker, 'last'); - const relativeChange = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const relativeChange = this.safeNumber (ticker, 'percentChange'); if (relativeChange !== -1) { open = last / this.sum (1, relativeChange); change = last - open; @@ -105268,11 +103655,11 @@ module.exports = class poloniex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24hr'), - 'low': this.safeFloat (ticker, 'low24hr'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high24hr'), + 'low': this.safeNumber (ticker, 'low24hr'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -105282,8 +103669,8 @@ module.exports = class poloniex extends Exchange { 'change': change, 'percentage': relativeChange * 100, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -105324,7 +103711,7 @@ module.exports = class poloniex extends Exchange { const code = this.safeCurrencyCode (id); const active = (currency['delisted'] === 0) && !currency['disabled']; const numericId = this.safeInteger (currency, 'id'); - const fee = this.safeFloat (currency, 'txFee'); + const fee = this.safeNumber (currency, 'txFee'); result[code] = { 'id': id, 'numericId': numericId, @@ -105415,13 +103802,18 @@ module.exports = class poloniex extends Exchange { } const side = this.safeString (trade, 'type'); let fee = undefined; - const price = this.safeFloat (trade, 'rate'); - const cost = this.safeFloat (trade, 'total'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const feeDisplay = this.safeString (trade, 'feeDisplay'); if (feeDisplay !== undefined) { const parts = feeDisplay.split (' '); - const feeCost = this.safeFloat (parts, 0); + const feeCost = this.safeNumber (parts, 0); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -105440,7 +103832,7 @@ module.exports = class poloniex extends Exchange { } } let takerOrMaker = undefined; - const takerAdjustment = this.safeFloat (trade, 'takerAdjustment'); + const takerAdjustment = this.safeNumber (trade, 'takerAdjustment'); if (takerAdjustment !== undefined) { takerOrMaker = 'taker'; } @@ -105686,9 +104078,9 @@ module.exports = class poloniex extends Exchange { if (resultingTrades !== undefined) { trades = this.parseTrades (resultingTrades, market); } - const price = this.safeFloat2 (order, 'price', 'rate'); - let remaining = this.safeFloat (order, 'amount'); - let amount = this.safeFloat (order, 'startingAmount'); + const price = this.safeNumber2 (order, 'price', 'rate'); + let remaining = this.safeNumber (order, 'amount'); + let amount = this.safeNumber (order, 'startingAmount'); let filled = undefined; let cost = 0; if (amount !== undefined) { @@ -105738,7 +104130,7 @@ module.exports = class poloniex extends Exchange { } const id = this.safeString (order, 'orderNumber'); let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -106235,11 +104627,11 @@ module.exports = class poloniex extends Exchange { const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit'; const type = this.safeString (transaction, 'type', defaultType); const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'paymentID'); // according to https://poloniex.com/fees/ - const feeCost = this.safeFloat (transaction, 'fee', 0); + const feeCost = this.safeNumber (transaction, 'fee', 0); if (type === 'withdrawal') { // poloniex withdrawal amount includes the fee amount = amount - feeCost; @@ -106323,7 +104715,7 @@ module.exports = class poloniex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],121:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],118:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -106331,6 +104723,7 @@ module.exports = class poloniex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, BadResponse, BadRequest, InvalidOrder, InsufficientFunds, AuthenticationError, ArgumentsRequired, InvalidAddress, RateLimitExceeded, DDoSProtection, BadSymbol } = require ('./base/errors'); const { TRUNCATE, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -106466,9 +104859,11 @@ module.exports = class probit extends Exchange { }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', 'CBC': 'CryptoBharatCoin', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'HBC': 'Hybrid Bank Cash', 'UNI': 'UNICORN Token', }, @@ -106517,11 +104912,11 @@ module.exports = class probit extends Exchange { const costPrecision = this.safeInteger (market, 'cost_precision'); const precision = { 'amount': 1 / Math.pow (10, amountPrecision), - 'price': this.safeFloat (market, 'price_increment'), + 'price': this.safeNumber (market, 'price_increment'), 'cost': 1 / Math.pow (10, costPrecision), }; - const takerFeeRate = this.safeFloat (market, 'taker_fee_rate'); - const makerFeeRate = this.safeFloat (market, 'maker_fee_rate'); + const takerFeeRate = this.safeNumber (market, 'taker_fee_rate'); + const makerFeeRate = this.safeNumber (market, 'maker_fee_rate'); result.push ({ 'id': id, 'info': market, @@ -106536,16 +104931,16 @@ module.exports = class probit extends Exchange { 'maker': makerFeeRate / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_cost'), - 'max': this.safeFloat (market, 'max_cost'), + 'min': this.safeNumber (market, 'min_cost'), + 'max': this.safeNumber (market, 'max_cost'), }, }, }); @@ -106632,7 +105027,7 @@ module.exports = class probit extends Exchange { // [ { 'amount': '0.015', 'priority': 1, 'currency_id': 'ETH' }, {} ] for (let j = 0; j < withdrawalFees.length; j++) { const withdrawalFee = withdrawalFees[j]; - const amount = this.safeFloat (withdrawalFee, 'amount'); + const amount = this.safeNumber (withdrawalFee, 'amount'); const priority = this.safeInteger (withdrawalFee, 'priority'); if ((amount !== undefined) && (priority !== undefined)) { fees.push (withdrawalFee); @@ -106640,7 +105035,7 @@ module.exports = class probit extends Exchange { } const withdrawalFeesByPriority = this.sortBy (fees, 'priority'); const withdrawalFee = this.safeValue (withdrawalFeesByPriority, 0, {}); - const fee = this.safeFloat (withdrawalFee, 'amount'); + const fee = this.safeNumber (withdrawalFee, 'amount'); result[code] = { 'id': id, 'code': code, @@ -106663,11 +105058,11 @@ module.exports = class probit extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (platform, 'min_deposit_amount'), + 'min': this.safeNumber (platform, 'min_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (platform, 'min_withdrawal_amount'), + 'min': this.safeNumber (platform, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -106697,11 +105092,11 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (balance, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'total'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -106753,14 +105148,6 @@ module.exports = class probit extends Exchange { return this.parseTickers (data, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -106808,8 +105195,8 @@ module.exports = class probit extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); - const close = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); + const close = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); let percentage = undefined; let open = undefined; if (change !== undefined) { @@ -106818,15 +105205,15 @@ module.exports = class probit extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -106968,16 +105355,13 @@ module.exports = class probit extends Exchange { marketId = this.safeString (trade, 'market_id', marketId); const symbol = this.safeSymbol (marketId, market, '-'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'order_id'); - const feeCost = this.safeFloat (trade, 'fee_amount'); + const feeCost = this.safeNumber (trade, 'fee_amount'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency_id'); @@ -107121,11 +105505,11 @@ module.exports = class probit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'start_time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_volume'), ]; } @@ -107224,37 +105608,24 @@ module.exports = class probit extends Exchange { const marketId = this.safeString (order, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'time')); - let price = this.safeFloat (order, 'limit_price'); - const filled = this.safeFloat (order, 'filled_quantity'); - let remaining = this.safeFloat (order, 'open_quantity'); - const canceledAmount = this.safeFloat (order, 'cancelled_quantity'); + let price = this.safeNumber (order, 'limit_price'); + const filled = this.safeNumber (order, 'filled_quantity'); + let remaining = this.safeNumber (order, 'open_quantity'); + const canceledAmount = this.safeNumber (order, 'cancelled_quantity'); if (canceledAmount !== undefined) { remaining = this.sum (remaining, canceledAmount); } - const amount = this.safeFloat (order, 'quantity', this.sum (filled, remaining)); - let cost = this.safeFloat2 (order, 'filled_cost', 'cost'); + const amount = this.safeNumber (order, 'quantity', this.sum (filled, remaining)); + const cost = this.safeNumber2 (order, 'filled_cost', 'cost'); if (type === 'market') { price = undefined; } - let average = undefined; - if (filled !== undefined) { - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if (cost !== undefined) { - if (filled > 0) { - average = cost / filled; - } - } - } let clientOrderId = this.safeString (order, 'client_order_id'); if (clientOrderId === '') { clientOrderId = undefined; } const timeInForce = this.safeStringUpper (order, 'time_in_force'); - return { + return this.safeOrder ({ 'id': id, 'info': order, 'clientOrderId': clientOrderId, @@ -107271,11 +105642,11 @@ module.exports = class probit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'average': average, + 'average': undefined, 'cost': cost, 'fee': undefined, 'trades': undefined, - }; + }); } costToPrecision (symbol, cost) { @@ -107305,7 +105676,7 @@ module.exports = class probit extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -107430,16 +105801,6 @@ module.exports = class probit extends Exchange { return this.parseDepositAddresses (data); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { // In order to use this method // you need to allow API withdrawal from the API Settings Page, and @@ -107470,7 +105831,7 @@ module.exports = class probit extends Exchange { parseTransaction (transaction, currency = undefined) { const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'destination_tag'); const txid = this.safeString (transaction, 'hash'); @@ -107479,7 +105840,7 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (transaction, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined && feeCost !== 0) { fee = { @@ -107609,13 +105970,14 @@ module.exports = class probit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],122:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],119:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -107791,11 +106153,11 @@ module.exports = class qtrade extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_buy_value'), + 'min': this.safeNumber (market, 'minimum_buy_value'), 'max': undefined, }, 'price': { @@ -107876,12 +106238,12 @@ module.exports = class qtrade extends Exchange { 'info': currency, 'type': type, 'name': name, - 'fee': this.safeFloat (config, 'withdraw_fee'), + 'fee': this.safeNumber (config, 'withdraw_fee'), 'precision': this.safeInteger (currency, 'precision'), 'active': active, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimum_order'), + 'min': this.safeNumber (currency, 'minimum_order'), 'max': undefined, }, 'price': { @@ -107916,11 +106278,11 @@ module.exports = class qtrade extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'market_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'market_volume'), ]; } @@ -107982,8 +106344,8 @@ module.exports = class qtrade extends Exchange { const result = []; for (let j = 0; j < prices.length; j++) { const priceAsString = prices[j]; - const price = this.safeFloat (prices, j); - const amount = this.safeFloat (bidasks, priceAsString); + const price = this.safeNumber (prices, j); + const amount = this.safeNumber (bidasks, priceAsString); result.push ([ price, amount ]); } orderbook[side] = result; @@ -108015,12 +106377,12 @@ module.exports = class qtrade extends Exchange { const marketId = this.safeString (ticker, 'id_hr'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeIntegerProduct (ticker, 'last_change', 0.001); - const previous = this.safeFloat (ticker, 'day_open'); - const last = this.safeFloat (ticker, 'last'); - const day_change = this.safeFloat (ticker, 'day_change'); + const previous = this.safeNumber (ticker, 'day_open'); + const last = this.safeNumber (ticker, 'last'); + const day_change = this.safeNumber (ticker, 'day_change'); let percentage = undefined; let change = undefined; - let average = this.safeFloat (ticker, 'day_avg_price'); + let average = this.safeNumber (ticker, 'day_avg_price'); if (day_change !== undefined) { percentage = day_change * 100; if (previous !== undefined) { @@ -108030,18 +106392,18 @@ module.exports = class qtrade extends Exchange { if ((average === undefined) && (last !== undefined) && (previous !== undefined)) { average = this.sum (last, previous) / 2; } - const baseVolume = this.safeFloat (ticker, 'day_volume_market'); - const quoteVolume = this.safeFloat (ticker, 'day_volume_base'); + const baseVolume = this.safeNumber (ticker, 'day_volume_market'); + const quoteVolume = this.safeNumber (ticker, 'day_volume_base'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'day_high'), - 'low': this.safeFloat (ticker, 'day_low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'day_high'), + 'low': this.safeNumber (ticker, 'day_low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': previous, @@ -108249,16 +106611,16 @@ module.exports = class qtrade extends Exchange { const side = this.safeString (trade, 'side'); const marketId = this.safeString (trade, 'market_string'); const symbol = this.safeSymbol (marketId, market, '_'); - let cost = this.safeFloat2 (trade, 'base_volume', 'base_amount'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'market_amount', 'amount'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - if (price !== undefined) { - cost = price * amount; - } + let cost = this.safeNumber2 (trade, 'base_volume', 'base_amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'market_amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'base_fee'); + const feeCost = this.safeNumber (trade, 'base_fee'); if (feeCost !== undefined) { const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; fee = { @@ -108315,7 +106677,7 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); account['used'] = 0; result[code] = account; } @@ -108325,10 +106687,10 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -108457,10 +106819,9 @@ module.exports = class qtrade extends Exchange { side = this.safeString (parts, 0); orderType = this.safeString (parts, 1); } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'market_amount'); - let remaining = this.safeFloat (order, 'market_amount_remaining'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'market_amount'); + const remaining = this.safeNumber (order, 'market_amount_remaining'); const open = this.safeValue (order, 'open', false); const closeReason = this.safeString (order, 'close_reason'); let status = undefined; @@ -108472,58 +106833,21 @@ module.exports = class qtrade extends Exchange { status = 'closed'; } const marketId = this.safeString (order, 'market_string'); - const symbol = this.safeSymbol (marketId, market, '_'); + market = this.safeMarket (marketId, market, '_'); + const symbol = market['symbol']; const rawTrades = this.safeValue (order, 'trades', []); const parsedTrades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id, 'side': side, 'type': orderType, }); - const numTrades = parsedTrades.length; - let lastTradeTimestamp = undefined; - let feeCost = undefined; - let cost = undefined; - if (numTrades > 0) { - feeCost = 0; - cost = 0; - filled = 0; - remaining = amount; - for (let i = 0; i < parsedTrades.length; i++) { - const trade = parsedTrades[i]; - feeCost = this.sum (trade['fee']['cost'], feeCost); - lastTradeTimestamp = this.safeInteger (trade, 'timestamp'); - cost = this.sum (trade['cost'], cost); - filled = this.sum (trade['amount'], filled); - remaining = Math.max (0, remaining - trade['amount']); - } - } - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; - fee = { - 'currency': feeCurrencyCode, - 'cost': feeCost, - }; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let average = undefined; - if (filled !== undefined) { - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': orderType, 'timeInForce': undefined, @@ -108531,15 +106855,16 @@ module.exports = class qtrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, - 'fee': fee, - 'cost': cost, + 'fee': undefined, + 'fees': undefined, + 'cost': undefined, 'trades': parsedTrades, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -109008,7 +107333,7 @@ module.exports = class qtrade extends Exchange { const tagTo = tag; const cancelRequested = this.safeValue (transaction, 'cancel_requested'); const type = (cancelRequested === undefined) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); let status = this.parseTransactionStatus (this.safeString (transaction, 'status')); @@ -109152,7 +107477,7 @@ module.exports = class qtrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],123:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],120:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); @@ -109340,8 +107665,8 @@ module.exports = class rightbtc extends Exchange { return result; } - divideSafeFloat (x, key, divisor) { - const value = this.safeFloat (x, key); + divideSafeNumber (x, key, divisor) { + const value = this.safeNumber (x, key); if (value !== undefined) { return value / divisor; } @@ -109351,12 +107676,12 @@ module.exports = class rightbtc extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); - const last = this.divideSafeFloat (ticker, 'last', 1e8); - const high = this.divideSafeFloat (ticker, 'high', 1e8); - const low = this.divideSafeFloat (ticker, 'low', 1e8); - const bid = this.divideSafeFloat (ticker, 'buy', 1e8); - const ask = this.divideSafeFloat (ticker, 'sell', 1e8); - const baseVolume = this.divideSafeFloat (ticker, 'vol24h', 1e8); + const last = this.divideSafeNumber (ticker, 'last', 1e8); + const high = this.divideSafeNumber (ticker, 'high', 1e8); + const low = this.divideSafeNumber (ticker, 'low', 1e8); + const bid = this.divideSafeNumber (ticker, 'buy', 1e8); + const ask = this.divideSafeNumber (ticker, 'sell', 1e8); + const baseVolume = this.divideSafeNumber (ticker, 'vol24h', 1e8); return { 'symbol': symbol, 'timestamp': timestamp, @@ -109460,9 +107785,9 @@ module.exports = class rightbtc extends Exchange { let id = this.safeString (trade, 'tid'); id = this.safeString (trade, 'trade_id', id); const orderId = this.safeString (trade, 'order_id'); - const price = this.divideSafeFloat (trade, 'price', 1e8); - let amount = this.safeFloat (trade, 'amount'); - amount = this.safeFloat (trade, 'quantity', amount); + const price = this.divideSafeNumber (trade, 'price', 1e8); + let amount = this.safeNumber (trade, 'amount'); + amount = this.safeNumber (trade, 'quantity', amount); if (amount !== undefined) { amount = amount / 1e8; } @@ -109559,8 +107884,8 @@ module.exports = class rightbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); // https://github.com/ccxt/ccxt/issues/3873 - account['free'] = this.divideSafeFloat (balance, 'balance', 1e8); - account['used'] = this.divideSafeFloat (balance, 'frozen', 1e8); + account['free'] = this.divideSafeNumber (balance, 'balance', 1e8); + account['used'] = this.divideSafeNumber (balance, 'frozen', 1e8); result[code] = account; } return this.parseBalance (result); @@ -109649,30 +107974,18 @@ module.exports = class rightbtc extends Exchange { } else if ('transactTime' in order) { timestamp = order['transactTime']; } - let price = this.safeFloat2 (order, 'limit', 'price'); + let price = this.safeNumber2 (order, 'limit', 'price'); if (price !== undefined) { price = price / 1e8; } - const amount = this.divideSafeFloat (order, 'quantity', 1e8); - let filled = this.divideSafeFloat (order, 'filled_quantity', 1e8); - let remaining = this.divideSafeFloat (order, 'rest', 1e8); - const cost = this.divideSafeFloat (order, 'cost', 1e8); + const amount = this.divideSafeNumber (order, 'quantity', 1e8); + const filled = this.divideSafeNumber (order, 'filled_quantity', 1e8); + const remaining = this.divideSafeNumber (order, 'rest', 1e8); + const cost = this.divideSafeNumber (order, 'cost', 1e8); // lines 483-494 should be generalized into a base class method - if (amount !== undefined) { - if (remaining === undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - if (filled === undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } - } const type = 'limit'; const side = this.safeStringLower (order, 'side'); - const feeCost = this.divideSafeFloat (order, 'min_fee', 1e8); + const feeCost = this.divideSafeNumber (order, 'min_fee', 1e8); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -109680,13 +107993,13 @@ module.exports = class rightbtc extends Exchange { feeCurrency = market['quote']; } fee = { - 'rate': this.safeFloat (order, 'fee'), + 'rate': this.safeNumber (order, 'fee'), 'cost': feeCost, 'currency': feeCurrency, }; } const trades = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -109708,7 +108021,7 @@ module.exports = class rightbtc extends Exchange { 'fee': fee, 'trades': trades, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -109912,7 +108225,7 @@ module.exports = class rightbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],124:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],121:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -109920,6 +108233,7 @@ module.exports = class rightbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, BadSymbol, BadRequest, InvalidOrder, ArgumentsRequired, OrderNotFound, InsufficientFunds, DDoSProtection } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110064,12 +108378,12 @@ module.exports = class ripio extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'min_amount'), - 'price': this.safeFloat (market, 'price_tick'), + 'amount': this.safeNumber (market, 'min_amount'), + 'price': this.safeNumber (market, 'price_tick'), }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -110077,15 +108391,15 @@ module.exports = class ripio extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_value'), + 'min': this.safeNumber (market, 'min_value'), 'max': undefined, }, }; const active = this.safeValue (market, 'enabled', true); const fees = this.safeValue (market, 'fees', []); const firstFee = this.safeValue (fees, 0, {}); - const maker = this.safeFloat (firstFee, 'maker_fee', 0.0); - const taker = this.safeFloat (firstFee, 'taker_fee', 0.0); + const maker = this.safeNumber (firstFee, 'maker_fee', 0.0); + const taker = this.safeNumber (firstFee, 'taker_fee', 0.0); result.push ({ 'id': id, 'symbol': symbol, @@ -110192,18 +108506,18 @@ module.exports = class ripio extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); const marketId = this.safeString (ticker, 'pair'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const average = this.safeFloat (ticker, 'avg'); + const last = this.safeNumber (ticker, 'last_price'); + const average = this.safeNumber (ticker, 'avg'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bid_volume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'ask_volume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bid_volume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'ask_volume'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -110345,15 +108659,14 @@ module.exports = class ripio extends Exchange { if (side !== undefined) { side = side.toLowerCase (); } - const price = this.safeFloat2 (trade, 'price', 'match_price'); - const amount = this.safeFloat2 (trade, 'amount', 'exchanged'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString2 (trade, 'price', 'match_price'); + const amountString = this.safeString2 (trade, 'amount', 'exchanged'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'pair'); market = this.safeMarket (marketId, market); - const feeCost = this.safeFloat (trade, takerOrMaker + '_fee'); + const feeCost = this.safeNumber (trade, takerOrMaker + '_fee'); const orderId = this.safeString (trade, takerOrMaker); let fee = undefined; if (feeCost !== undefined) { @@ -110427,11 +108740,11 @@ module.exports = class ripio extends Exchange { const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -110690,16 +109003,16 @@ module.exports = class ripio extends Exchange { // } // const id = this.safeString (order, 'order_id'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat (order, 'notional'); + const amount = this.safeNumber (order, 'amount'); + let cost = this.safeNumber (order, 'notional'); const type = this.safeStringLower (order, 'order_type'); const priceField = (type === 'market') ? 'fill_price' : 'limit_price'; - const price = this.safeFloat (order, priceField); + const price = this.safeNumber (order, priceField); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeTimestamp (order, 'created_at'); let average = this.safeValue (order, 'fill_price'); - let filled = this.safeFloat (order, 'filled'); + let filled = this.safeNumber (order, 'filled'); let remaining = undefined; const fills = this.safeValue (order, 'fills'); let trades = undefined; @@ -110734,7 +109047,7 @@ module.exports = class ripio extends Exchange { } const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); return { 'id': id, 'clientOrderId': undefined, @@ -110860,13 +109173,14 @@ module.exports = class ripio extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],125:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],122:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110977,14 +109291,14 @@ module.exports = class southxchange extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const deposited = this.safeFloat (balance, 'Deposited'); - const unconfirmed = this.safeFloat (balance, 'Unconfirmed'); + const deposited = this.safeString (balance, 'Deposited'); + const unconfirmed = this.safeString (balance, 'Unconfirmed'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'Available'); - account['total'] = this.sum (deposited, unconfirmed); + account['free'] = this.safeString (balance, 'Available'); + account['total'] = Precise.stringAdd (deposited, unconfirmed); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -111002,16 +109316,16 @@ module.exports = class southxchange extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'Last'); + const last = this.safeNumber (ticker, 'Last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'Bid'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -111019,9 +109333,9 @@ module.exports = class southxchange extends Exchange { 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'Variation24Hr'), + 'percentage': this.safeNumber (ticker, 'Variation24Hr'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume24Hr'), + 'baseVolume': this.safeNumber (ticker, 'Volume24Hr'), 'quoteVolume': undefined, 'info': ticker, }; @@ -111055,14 +109369,11 @@ module.exports = class southxchange extends Exchange { parseTrade (trade, market) { const timestamp = this.safeTimestamp (trade, 'At'); - const price = this.safeFloat (trade, 'Price'); - const amount = this.safeFloat (trade, 'Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'Price'); + const amountString = this.safeString (trade, 'Amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'Type'); let symbol = undefined; if (market !== undefined) { @@ -111103,21 +109414,13 @@ module.exports = class southxchange extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const timestamp = undefined; - const price = this.safeFloat (order, 'LimitPrice'); - const amount = this.safeFloat (order, 'OriginalAmount'); - const remaining = this.safeFloat (order, 'Amount'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - cost = price * amount; - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'LimitPrice'); + const amount = this.safeNumber (order, 'OriginalAmount'); + const remaining = this.safeNumber (order, 'Amount'); const type = 'limit'; const side = this.safeStringLower (order, 'Type'); const id = this.safeString (order, 'Code'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -111132,15 +109435,14 @@ module.exports = class southxchange extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'filled': filled, + 'cost': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -111273,8 +109575,8 @@ module.exports = class southxchange extends Exchange { const type = this.safeString (item, 'Type'); const ledgerEntryType = this.parseLedgerEntryType (type); const code = this.safeCurrencyCode (this.safeString (item, 'CurrencyCode'), currency); - let amount = this.safeFloat (item, 'Amount'); - const after = this.safeFloat (item, 'TotalBalance'); + let amount = this.safeNumber (item, 'Amount'); + const after = this.safeNumber (item, 'TotalBalance'); let before = undefined; if (amount !== undefined) { if (after !== undefined) { @@ -111445,7 +109747,7 @@ module.exports = class southxchange extends Exchange { // } // const id = this.safeString (transaction, 'MovementId'); - const amount = this.safeFloat (transaction, 'Amount'); + const amount = this.safeNumber (transaction, 'Amount'); const address = this.safeString (transaction, 'Address'); const addressTo = address; const addressFrom = undefined; @@ -111560,7 +109862,7 @@ module.exports = class southxchange extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],126:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],123:[function(require,module,exports){ (function (module, exports) { 'use strict'; @@ -115088,7 +113390,7 @@ module.exports = class southxchange extends Exchange { }; })(typeof module === 'undefined' || module, this); -},{"buffer":188}],127:[function(require,module,exports){ +},{"buffer":184}],124:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -121077,7 +119379,7 @@ module.exports = class southxchange extends Exchange { return CryptoJS; })); -},{}],128:[function(require,module,exports){ +},{}],125:[function(require,module,exports){ 'use strict'; var elliptic = exports; @@ -121101,7 +119403,7 @@ elliptic.curves = require('./elliptic/curves'); elliptic.ec = require('./elliptic/ec'); elliptic.eddsa = require('./elliptic/eddsa'); -},{"./elliptic/curve":131,"./elliptic/curves":134,"./elliptic/ec":135,"./elliptic/eddsa":138,"./elliptic/utils":142}],129:[function(require,module,exports){ +},{"./elliptic/curve":128,"./elliptic/curves":131,"./elliptic/ec":132,"./elliptic/eddsa":135,"./elliptic/utils":139}],126:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -121478,7 +119780,7 @@ BasePoint.prototype.dblp = function dblp(k) { return r; }; -},{"../../../../BN/bn":126,"../../elliptic":128}],130:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],127:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -121913,7 +120215,7 @@ Point.prototype.eqXToP = function eqXToP(x) { Point.prototype.toP = Point.prototype.normalize; Point.prototype.mixedAdd = Point.prototype.add; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],131:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],128:[function(require,module,exports){ 'use strict'; var curve = exports; @@ -121923,7 +120225,7 @@ curve.short = require('./short'); curve.mont = require('./mont'); curve.edwards = require('./edwards'); -},{"./base":129,"./edwards":130,"./mont":132,"./short":133}],132:[function(require,module,exports){ +},{"./base":126,"./edwards":127,"./mont":129,"./short":130}],129:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -122105,7 +120407,7 @@ Point.prototype.getX = function getX() { return this.x.fromRed(); }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],133:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],130:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -123045,7 +121347,7 @@ JPoint.prototype.isInfinity = function isInfinity() { return this.z.cmpn(0) === 0; }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],134:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],131:[function(require,module,exports){ 'use strict'; var curves = exports; @@ -123251,7 +121553,7 @@ defineCurve('secp256k1', { ] }); -},{"../elliptic":128,"./precomputed/secp256k1":141}],135:[function(require,module,exports){ +},{"../elliptic":125,"./precomputed/secp256k1":138}],132:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123493,7 +121795,7 @@ EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { throw new Error('Unable to find valid recovery factor'); }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../../hmac-drbg/hmac-drbg":143,"./key":136,"./signature":137}],136:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../../hmac-drbg/hmac-drbg":140,"./key":133,"./signature":134}],133:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123614,7 +121916,7 @@ KeyPair.prototype.inspect = function inspect() { ' pub: ' + (this.pub && this.pub.inspect()) + ' >'; }; -},{"../../../../BN/bn":126,"../../elliptic":128}],137:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],134:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123640,7 +121942,7 @@ function Signature(options, enc) { } module.exports = Signature; -},{"../../../../BN/bn":126,"../../elliptic":128}],138:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],135:[function(require,module,exports){ 'use strict'; var curves = require('../curves'); @@ -123787,7 +122089,7 @@ EDDSA.prototype.isPoint = function isPoint(val) { return val instanceof this.pointClass; }; -},{"../../../../../base/functions/encode":11,"../../../../BN/bn.js":126,"../../../../crypto-js/crypto-js":127,"../curves":134,"../utils":142,"./key":139,"./signature":140}],139:[function(require,module,exports){ +},{"../../../../../base/functions/encode":12,"../../../../BN/bn.js":123,"../../../../crypto-js/crypto-js":124,"../curves":131,"../utils":139,"./key":136,"./signature":137}],136:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -123889,7 +122191,7 @@ KeyPair.prototype.getPublic = function getPublic(enc) { module.exports = KeyPair; -},{"../utils":142}],140:[function(require,module,exports){ +},{"../utils":139}],137:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123956,7 +122258,7 @@ Signature.prototype.toHex = function toHex() { module.exports = Signature; -},{"../../../../BN/bn":126,"../utils":142}],141:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../utils":139}],138:[function(require,module,exports){ module.exports = { doubles: { step: 4, @@ -124738,7 +123040,7 @@ module.exports = { } }; -},{}],142:[function(require,module,exports){ +},{}],139:[function(require,module,exports){ 'use strict'; var utils = exports; @@ -124954,7 +123256,7 @@ utils.encode = function encode(arr, enc) { return arr; }; -},{"../../../BN/bn":126}],143:[function(require,module,exports){ +},{"../../../BN/bn":123}],140:[function(require,module,exports){ 'use strict'; var CryptoJS = require('../../../crypto-js/crypto-js'); @@ -125070,7 +123372,7 @@ HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { return utils.wordArrayToBuffer(res); }; -},{"../../../../base/functions/encode":11,"../../../crypto-js/crypto-js":127,"../elliptic/utils":142}],144:[function(require,module,exports){ +},{"../../../../base/functions/encode":12,"../../../crypto-js/crypto-js":124,"../elliptic/utils":139}],141:[function(require,module,exports){ 'use strict'; var fetch = require('../node-fetch/index'); @@ -125111,7 +123413,7 @@ module.exports = function (context) { }; }; -},{"../node-fetch/index":145}],145:[function(require,module,exports){ +},{"../node-fetch/index":142}],142:[function(require,module,exports){ (function (global,Buffer){ 'use strict'; @@ -126679,7 +124981,7 @@ exports.Response = Response; exports.FetchError = FetchError; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":188,"http":230,"https":193,"stream":229,"url":236,"zlib":187}],146:[function(require,module,exports){ +},{"buffer":184,"http":226,"https":189,"stream":225,"url":232,"zlib":183}],143:[function(require,module,exports){ (function (Buffer){ /*! * RSA library for Node.js @@ -126906,7 +125208,7 @@ module.exports = (function () { })(); }).call(this,require("buffer").Buffer) -},{"./formats/formats.js":153,"./libs/rsa.js":157,"./schemes/schemes.js":159,"./utils":160,"buffer":188}],147:[function(require,module,exports){ +},{"./formats/formats.js":150,"./libs/rsa.js":154,"./schemes/schemes.js":156,"./utils":157,"buffer":184}],144:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. @@ -126921,7 +125223,7 @@ module.exports = { }; -},{}],148:[function(require,module,exports){ +},{}],145:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. var errors = require('./errors'); @@ -126944,7 +125246,7 @@ for (var e in errors) { module.exports[e] = errors[e]; } -},{"./errors":147,"./reader":149,"./types":150}],149:[function(require,module,exports){ +},{"./errors":144,"./reader":146,"./types":147}],146:[function(require,module,exports){ (function (Buffer){ // Copyright 2011 Mark Cavage All rights reserved. @@ -127210,7 +125512,7 @@ Reader.prototype._readTag = function (tag) { module.exports = Reader; }).call(this,require("buffer").Buffer) -},{"./errors":147,"./types":150,"assert":183,"buffer":188}],150:[function(require,module,exports){ +},{"./errors":144,"./types":147,"assert":179,"buffer":184}],147:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. @@ -127248,7 +125550,7 @@ module.exports = { Context: 128 }; -},{}],151:[function(require,module,exports){ +},{}],148:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. // If you have no idea what ASN.1 or BER is, see this: @@ -127267,7 +125569,7 @@ module.exports = { BerReader: Ber.Reader, }; -},{"./ber/index":148}],152:[function(require,module,exports){ +},{"./ber/index":145}],149:[function(require,module,exports){ var _ = require('../utils')._; var utils = require('../utils'); @@ -127340,7 +125642,7 @@ module.exports = { } }; -},{"../utils":160}],153:[function(require,module,exports){ +},{"../utils":157}],150:[function(require,module,exports){ var _ = require('../utils')._; module.exports = { @@ -127373,7 +125675,7 @@ module.exports = { }, }; -},{"../utils":160,"./components":152,"./pkcs1":154,"./pkcs8":155}],154:[function(require,module,exports){ +},{"../utils":157,"./components":149,"./pkcs1":151,"./pkcs8":152}],151:[function(require,module,exports){ (function (Buffer){ var ber = require('../asn1/index').Ber; var _ = require('../utils')._; @@ -127525,7 +125827,7 @@ module.exports = { }; }).call(this,require("buffer").Buffer) -},{"../asn1/index":151,"../utils":160,"buffer":188}],155:[function(require,module,exports){ +},{"../asn1/index":148,"../utils":157,"buffer":184}],152:[function(require,module,exports){ (function (Buffer){ var ber = require('../asn1/index').Ber; var _ = require('../utils')._; @@ -127716,7 +126018,7 @@ module.exports = { }; }).call(this,require("buffer").Buffer) -},{"../asn1/index":151,"../utils":160,"buffer":188}],156:[function(require,module,exports){ +},{"../asn1/index":148,"../utils":157,"buffer":184}],153:[function(require,module,exports){ (function (Buffer){ /* * Basic JavaScript BN library - subset useful for RSA encryption. @@ -128972,7 +127274,7 @@ BigInteger.prototype.square = bnSquare; module.exports = BigInteger; }).call(this,require("buffer").Buffer) -},{"../utils":160,"buffer":188}],157:[function(require,module,exports){ +},{"../utils":157,"buffer":184}],154:[function(require,module,exports){ /* * RSA Encryption / Decryption with PKCS1 v2 Padding. * @@ -129121,7 +127423,7 @@ module.exports.Key = (function () { })(); -},{"../schemes/schemes.js":159,"../utils":160,"../utils.js":160,"./jsbn.js":156}],158:[function(require,module,exports){ +},{"../schemes/schemes.js":156,"../utils":157,"../utils.js":157,"./jsbn.js":153}],155:[function(require,module,exports){ (function (Buffer){ /** * PKCS1 padding and signature scheme @@ -129301,7 +127603,7 @@ function wordArrayToBuffer(wordArray) { } }).call(this,require("buffer").Buffer) -},{"../../crypto-js/crypto-js":127,"../libs/jsbn":156,"buffer":188,"constants":190}],159:[function(require,module,exports){ +},{"../../crypto-js/crypto-js":124,"../libs/jsbn":153,"buffer":184,"constants":186}],156:[function(require,module,exports){ module.exports = { pkcs1: require('./pkcs1'), @@ -129324,7 +127626,7 @@ module.exports = { } }; -},{"./pkcs1":158}],160:[function(require,module,exports){ +},{"./pkcs1":155}],157:[function(require,module,exports){ /* * Utils functions * @@ -129424,7 +127726,7 @@ module.exports.trimSurroundingText = function (data, opening, closing) { return data.substring(trimStartIndex, trimEndIndex); } -},{}],161:[function(require,module,exports){ +},{}],158:[function(require,module,exports){ 'use strict'; var replace = String.prototype.replace; @@ -129444,7 +127746,7 @@ module.exports = { RFC3986: 'RFC3986' }; -},{}],162:[function(require,module,exports){ +},{}],159:[function(require,module,exports){ 'use strict'; var stringify = require('./stringify'); @@ -129457,7 +127759,7 @@ module.exports = { stringify: stringify }; -},{"./formats":161,"./parse":163,"./stringify":164}],163:[function(require,module,exports){ +},{"./formats":158,"./parse":160,"./stringify":161}],160:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -129701,7 +128003,7 @@ module.exports = function (str, opts) { return utils.compact(obj); }; -},{"./utils":165}],164:[function(require,module,exports){ +},{"./utils":162}],161:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -129972,7 +128274,7 @@ module.exports = function (object, opts) { return joined.length > 0 ? prefix + joined : ''; }; -},{"./formats":161,"./utils":165}],165:[function(require,module,exports){ +},{"./formats":158,"./utils":162}],162:[function(require,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty; @@ -130204,13 +128506,14 @@ module.exports = { merge: merge }; -},{}],166:[function(require,module,exports){ +},{}],163:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -130393,6 +128696,7 @@ module.exports = class stex extends Exchange { 'BITSW': 'BITS', 'BHD': 'Bithold', 'BTH': 'Bithereum', + 'MPH': 'Chasyr Token', 'SBTC': 'SBTCT', // SiamBitcoin }, 'options': { @@ -130456,7 +128760,7 @@ module.exports = class stex extends Exchange { // differentiated fees for each particular method const code = this.safeCurrencyCode (this.safeString (currency, 'code')); const precision = this.safeInteger (currency, 'precision'); - const fee = this.safeFloat (currency, 'withdrawal_fee_const'); // todo: redesign + const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign const active = this.safeValue (currency, 'active', true); result[code] = { 'id': id, @@ -130473,11 +128777,11 @@ module.exports = class stex extends Exchange { 'price': { 'min': Math.pow (10, -precision), 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (currency, 'minimum_deposit_amount'), + 'min': this.safeNumber (currency, 'minimum_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal_amount'), + 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'), 'max': undefined, }, }, @@ -130538,11 +128842,11 @@ module.exports = class stex extends Exchange { 'price': this.safeInteger (market, 'market_precision'), }; const active = this.safeValue (market, 'active'); - const minBuyPrice = this.safeFloat (market, 'min_buy_price'); - const minSellPrice = this.safeFloat (market, 'min_sell_price'); + const minBuyPrice = this.safeNumber (market, 'min_buy_price'); + const minSellPrice = this.safeNumber (market, 'min_sell_price'); const minPrice = Math.max (minBuyPrice, minSellPrice); - const buyFee = this.safeFloat (market, 'buy_fee_percent') / 100; - const sellFee = this.safeFloat (market, 'sell_fee_percent') / 100; + const buyFee = this.safeNumber (market, 'buy_fee_percent') / 100; + const sellFee = this.safeNumber (market, 'sell_fee_percent') / 100; const fee = Math.max (buyFee, sellFee); result.push ({ 'id': id, @@ -130561,7 +128865,7 @@ module.exports = class stex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_order_amount'), + 'min': this.safeNumber (market, 'min_order_amount'), 'max': undefined, }, 'price': { 'min': minPrice, 'max': undefined }, @@ -130725,8 +129029,8 @@ module.exports = class stex extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString2 (ticker, 'id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -130739,11 +129043,11 @@ module.exports = class stex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -130753,20 +129057,12 @@ module.exports = class stex extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volumeQuote'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volumeQuote'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker (params); @@ -130832,11 +129128,11 @@ module.exports = class stex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -130911,12 +129207,11 @@ module.exports = class stex extends Exchange { // const id = this.safeString (trade, 'id'); const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; @@ -131029,11 +129324,11 @@ module.exports = class stex extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen_balance'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -131092,9 +129387,9 @@ module.exports = class stex extends Exchange { const marketId = this.safeString2 (order, 'currency_pair_id', 'currency_pair_name'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (order, 'timestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'initial_amount'); - const filled = this.safeFloat (order, 'processed_amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'initial_amount'); + const filled = this.safeNumber (order, 'processed_amount'); let remaining = undefined; let cost = undefined; if (filled !== undefined) { @@ -131124,7 +129419,7 @@ module.exports = class stex extends Exchange { 'order': id, }); } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); const result = { 'info': order, 'id': id, @@ -131155,7 +129450,7 @@ module.exports = class stex extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'amount'); + const feeCost = this.safeNumber (fees[i], 'amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -131739,13 +130034,13 @@ module.exports = class stex extends Exchange { code = currency['code']; } const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status')); const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts'); const updated = this.safeTimestamp (transaction, 'updated_ts'); const txid = this.safeString (transaction, 'txid'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'fee_currency_id', 'deposit_fee_currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -131981,8 +130276,8 @@ module.exports = class stex extends Exchange { for (let i = 0; i < data.length; i++) { const id = this.safeString (data[i], 'id'); const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (data[i], 'withdrawal_fee_const'); - depositFees[code] = this.safeFloat (data[i], 'deposit_fee_const'); + withdrawFees[code] = this.safeNumber (data[i], 'withdrawal_fee_const'); + depositFees[code] = this.safeNumber (data[i], 'deposit_fee_const'); } return { 'withdraw': withdrawFees, @@ -132011,7 +130306,7 @@ module.exports = class stex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],167:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],164:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -132045,13 +130340,14 @@ module.exports = class surbitcoin extends foxbit { } }; -},{"./foxbit.js":87}],168:[function(require,module,exports){ +},{"./foxbit.js":85}],165:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -132219,8 +130515,8 @@ module.exports = class therock extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const buy_fee = this.safeFloat (market, 'buy_fee'); - const sell_fee = this.safeFloat (market, 'sell_fee'); + const buy_fee = this.safeNumber (market, 'buy_fee'); + const sell_fee = this.safeNumber (market, 'sell_fee'); let taker = Math.max (buy_fee, sell_fee); taker = taker / 100; const maker = taker; @@ -132241,11 +130537,11 @@ module.exports = class therock extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_quantity_offer'), + 'min': this.safeNumber (market, 'minimum_quantity_offer'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'minimum_price_offer'), + 'min': this.safeNumber (market, 'minimum_price_offer'), 'max': undefined, }, 'cost': { @@ -132269,11 +130565,11 @@ module.exports = class therock extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'trading_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'trading_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -132292,27 +130588,27 @@ module.exports = class therock extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'close'), // previous day close, if any + 'previousClose': this.safeNumber (ticker, 'close'), // previous day close, if any 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_traded'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume_traded'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -132387,14 +130683,11 @@ module.exports = class therock extends Exchange { const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; let feeCost = undefined; const transactions = this.safeValue (trade, 'transactions', []); @@ -132404,7 +130697,7 @@ module.exports = class therock extends Exchange { if (feeCost === undefined) { feeCost = 0; } - feeCost = this.sum (feeCost, this.safeFloat (feeTransactions[i], 'price')); + feeCost = this.sum (feeCost, this.safeNumber (feeTransactions[i], 'price')); } if (feeCost !== undefined) { fee = { @@ -132559,7 +130852,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (item, 'price'); + const amount = this.safeNumber (item, 'price'); const timestamp = this.parse8601 (this.safeString (item, 'date')); const status = 'ok'; return { @@ -132791,7 +131084,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'price'); + const amount = this.safeNumber (transaction, 'price'); const timestamp = this.parse8601 (this.safeString (transaction, 'date')); const status = 'ok'; // todo parse tags @@ -132966,15 +131259,15 @@ module.exports = class therock extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'date')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'amount_unfilled'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amount_unfilled'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let trades = this.safeValue (order, 'trades'); let cost = undefined; let average = undefined; @@ -133001,7 +131294,7 @@ module.exports = class therock extends Exchange { cost = 0; } } - const stopPrice = this.safeFloat (order, 'conditional_price'); + const stopPrice = this.safeNumber (order, 'conditional_price'); return { 'id': id, 'clientOrderId': undefined, @@ -133279,13 +131572,14 @@ module.exports = class therock extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],169:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],166:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -133464,11 +131758,11 @@ module.exports = class tidebit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -133493,15 +131787,15 @@ module.exports = class tidebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'ask': this.safeFloat (ticker, 'sell'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'ask': this.safeNumber (ticker, 'sell'), 'bidVolume': undefined, 'askVolume': undefined, 'vwap': undefined, @@ -133512,7 +131806,7 @@ module.exports = class tidebit extends Exchange { 'percentage': undefined, 'previousClose': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -133546,9 +131840,14 @@ module.exports = class tidebit extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -133593,11 +131892,11 @@ module.exports = class tidebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -133683,18 +131982,12 @@ module.exports = class tidebit extends Exchange { const id = this.safeString (order, 'id'); const type = this.safeString (order, 'ord_type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const filled = this.safeFloat (order, 'executed_volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - let cost = undefined; - if (price !== undefined) { - if (filled !== undefined) { - cost = price * filled; - } - } - const average = this.safeFloat (order, 'avg_price'); - return { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const filled = this.safeNumber (order, 'executed_volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -133711,12 +132004,12 @@ module.exports = class tidebit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': average, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -133824,11 +132117,12 @@ module.exports = class tidebit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],170:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],167:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class tidex extends Exchange { describe () { @@ -133910,6 +132204,7 @@ module.exports = class tidex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.1 / 100, @@ -133954,19 +132249,48 @@ module.exports = class tidex extends Exchange { async fetchCurrencies (params = {}) { const response = await this.webGetCurrency (params); + // + // [ + // { + // "id":2, + // "symbol":"BTC", + // "type":2, + // "name":"Bitcoin", + // "amountPoint":8, + // "depositEnable":true, + // "depositMinAmount":0.0005, + // "withdrawEnable":true, + // "withdrawFee":0.0004, + // "withdrawMinAmount":0.0005, + // "settings":{ + // "Blockchain":"https://blockchair.com/bitcoin/", + // "TxUrl":"https://blockchair.com/bitcoin/transaction/{0}", + // "AddrUrl":"https://blockchair.com/bitcoin/address/{0}", + // "ConfirmationCount":3, + // "NeedMemo":false + // }, + // "visible":true, + // "isDelisted":false + // } + // ] + // const result = {}; for (let i = 0; i < response.length; i++) { const currency = response[i]; const id = this.safeString (currency, 'symbol'); - const precision = currency['amountPoint']; + const precision = this.safeInteger (currency, 'amountPoint'); const code = this.safeCurrencyCode (id); - let active = currency['visible'] === true; - const canWithdraw = currency['withdrawEnable'] === true; - const canDeposit = currency['depositEnable'] === true; + const visible = this.safeValue (currency, 'visible'); + let active = visible === true; + const withdrawEnable = this.safeValue (currency, 'withdrawEnable'); + const depositEnable = this.safeValue (currency, 'depositEnable'); + const canWithdraw = withdrawEnable === true; + const canDeposit = depositEnable === true; if (!canWithdraw || !canDeposit) { active = false; } const name = this.safeString (currency, 'name'); + const fee = this.safeNumber (currency, 'withdrawFee'); result[code] = { 'id': id, 'code': code, @@ -133976,7 +132300,7 @@ module.exports = class tidex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': currency['withdrawFee'], + 'fee': fee, }, 'deposit': { 'active': canDeposit, @@ -133997,11 +132321,11 @@ module.exports = class tidex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawMinAmount'), + 'min': this.safeNumber (currency, 'withdrawMinAmount'), 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'depositMinAmount'), + 'min': this.safeNumber (currency, 'depositMinAmount'), 'max': undefined, }, }, @@ -134011,26 +132335,25 @@ module.exports = class tidex extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615861869, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":3.0, + // "min_amount":0.001, + // "max_amount":1000000.0, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.1, + // }, + // }, + // } + // const markets = response['pairs']; const keys = Object.keys (markets); const result = []; @@ -134047,19 +132370,20 @@ module.exports = class tidex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }, }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -134068,7 +132392,7 @@ module.exports = class tidex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -134089,11 +132413,11 @@ module.exports = class tidex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (funds, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'value'); - account['used'] = this.safeFloat (balance, 'inOrders'); + account['free'] = this.safeString (balance, 'value'); + account['used'] = this.safeString (balance, 'inOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -134165,16 +132489,16 @@ module.exports = class tidex extends Exchange { timestamp = undefined; } } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -134183,9 +132507,9 @@ module.exports = class tidex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -134233,16 +132557,19 @@ module.exports = class tidex extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const orderId = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = 'limit'; // all trades are still limit trades let takerOrMaker = undefined; let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -134261,12 +132588,6 @@ module.exports = class tidex extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': orderId, @@ -134322,17 +132643,18 @@ module.exports = class tidex extends Exchange { let status = 'open'; let filled = 0.0; let remaining = amount; - if ('return' in response) { - id = this.safeString (response['return'], 'order_id'); + const returnResult = this.safeValue (response, 'return'); + if (returnResult !== undefined) { + id = this.safeString (returnResult, 'order_id'); if (id === '0') { - id = this.safeString (response['return'], 'init_order_id'); + id = this.safeString (returnResult, 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (returnResult, 'received', filled); + remaining = this.safeNumber (returnResult, 'remains', amount); } const timestamp = this.milliseconds (); - return { + return this.safeOrder ({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -134342,7 +132664,7 @@ module.exports = class tidex extends Exchange { 'type': type, 'side': side, 'price': price, - 'cost': price * filled, + 'cost': undefined, 'amount': amount, 'remaining': remaining, 'filled': filled, @@ -134352,7 +132674,7 @@ module.exports = class tidex extends Exchange { 'clientOrderId': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -134381,23 +132703,15 @@ module.exports = class tidex extends Exchange { const symbol = this.safeSymbol (marketId, market); let remaining = undefined; let amount = undefined; - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; + const price = this.safeNumber (order, 'rate'); if ('start_amount' in order) { - amount = this.safeFloat (order, 'start_amount'); - remaining = this.safeFloat (order, 'amount'); + amount = this.safeNumber (order, 'start_amount'); + remaining = this.safeNumber (order, 'amount'); } else { - remaining = this.safeFloat (order, 'amount'); - } - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } + remaining = this.safeNumber (order, 'amount'); } const fee = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -134411,15 +132725,15 @@ module.exports = class tidex extends Exchange { 'side': this.safeString (order, 'type'), 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -134609,11 +132923,12 @@ module.exports = class tidex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],171:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],168:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, PermissionDenied, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, RateLimitExceeded, NotSupported, BadRequest, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class timex extends Exchange { describe () { @@ -135062,11 +133377,11 @@ module.exports = class timex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'totalBalance'); - account['used'] = this.safeFloat (balance, 'lockedBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + account['used'] = this.safeString (balance, 'lockedBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -135427,7 +133742,7 @@ module.exports = class timex extends Exchange { const result = this.safeValue (response, 0, {}); return { 'info': response, - 'maker': this.safeFloat (result, 'fee'), + 'maker': this.safeNumber (result, 'fee'), 'taker': undefined, }; } @@ -135464,18 +133779,18 @@ module.exports = class timex extends Exchange { 'amount': this.precisionFromString (this.safeString (market, 'quantityIncrement')), 'price': this.precisionFromString (this.safeString (market, 'tickSize')), }; - const amountIncrement = this.safeFloat (market, 'quantityIncrement'); - const minBase = this.safeFloat (market, 'baseMinSize'); + const amountIncrement = this.safeNumber (market, 'quantityIncrement'); + const minBase = this.safeNumber (market, 'baseMinSize'); const minAmount = Math.max (amountIncrement, minBase); - const priceIncrement = this.safeFloat (market, 'tickSize'); - const minCost = this.safeFloat (market, 'quoteMinSize'); + const priceIncrement = this.safeNumber (market, 'tickSize'); + const minCost = this.safeNumber (market, 'quoteMinSize'); const limits = { 'amount': { 'min': minAmount, 'max': undefined }, 'price': { 'min': priceIncrement, 'max': undefined }, 'cost': { 'min': Math.max (minCost, minAmount * priceIncrement), 'max': undefined }, }; - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); return { 'id': id, 'symbol': symbol, @@ -135536,7 +133851,7 @@ module.exports = class timex extends Exchange { const name = this.safeString (currency, 'name'); const precision = this.safeInteger (currency, 'decimals'); const active = this.safeValue (currency, 'active'); - // const fee = this.safeFloat (currency, 'withdrawalFee'); + // const fee = this.safeNumber (currency, 'withdrawalFee'); const feeString = this.safeString (currency, 'withdrawalFee'); const tradeDecimals = this.safeInteger (currency, 'tradeDecimals'); let fee = undefined; @@ -135573,14 +133888,6 @@ module.exports = class timex extends Exchange { }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // // { @@ -135600,8 +133907,8 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '/'); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -135617,11 +133924,11 @@ module.exports = class timex extends Exchange { 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -135631,8 +133938,8 @@ module.exports = class timex extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'volumeQuote'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volumeQuote'), }; } @@ -135651,23 +133958,27 @@ module.exports = class timex extends Exchange { // fetchMyTrades, fetchOrder (private) // // { - // "fee": "0.3", - // "id": 100, - // "makerOrTaker": "MAKER", - // "makerOrderId": "string", - // "price": "0.017", - // "quantity": "0.3", + // "id": "7613414", + // "makerOrderId": "0x8420af060722f560098f786a2894d4358079b6ea5d14b395969ed77bc87a623a", + // "takerOrderId": "0x1235ef158a361815b54c9988b6241c85aedcbc1fe81caf8df8587d5ab0373d1a", + // "symbol": "LTCUSDT", // "side": "BUY", - // "symbol": "TIMEETH", - // "takerOrderId": "string", - // "timestamp": "2019-12-08T04:54:11.171Z" - // } + // "quantity": "0.2", + // "fee": "0.22685", + // "feeToken": "USDT", + // "price": "226.85", + // "makerOrTaker": "TAKER", + // "timestamp": "2021-04-09T15:39:45.608" + // } // const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeStringLower2 (trade, 'direction', 'side'); const takerOrMaker = this.safeStringLower (trade, 'makerOrTaker'); @@ -135676,18 +133987,14 @@ module.exports = class timex extends Exchange { orderId = this.safeString (trade, takerOrMaker + 'OrderId'); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); + const feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'feeToken')); if (feeCost !== undefined) { - const feeCurrency = (market === undefined) ? undefined : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrency, }; } - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = this.costToPrecision (symbol, amount * price); - } return { 'info': trade, 'id': id, @@ -135719,11 +134026,11 @@ module.exports = class timex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -135754,14 +134061,12 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'filledQuantity'); - const canceledQuantity = this.safeFloat (order, 'cancelledQuantity'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'filledQuantity'); + const canceledQuantity = this.safeNumber (order, 'cancelledQuantity'); let status = undefined; if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0.0); if (filled >= amount) { status = 'closed'; } else if ((canceledQuantity !== undefined) && (canceledQuantity > 0)) { @@ -135770,30 +134075,19 @@ module.exports = class timex extends Exchange { status = 'open'; } } - const cost = parseFloat (this.costToPrecision (symbol, price * filled)); - const fee = undefined; - let lastTradeTimestamp = undefined; - let trades = undefined; - const rawTrades = this.safeValue (order, 'trades'); - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'order': id, - }); - } - if (trades !== undefined) { - const numTrades = trades.length; - if (numTrades > 0) { - lastTradeTimestamp = trades[numTrades - 1]['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'order': id, + 'type': type, + }); const clientOrderId = this.safeString (order, 'clientOrderId'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': undefined, @@ -135802,14 +134096,14 @@ module.exports = class timex extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { @@ -135850,13 +134144,14 @@ module.exports = class timex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],172:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],169:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, PermissionDenied, AddressPending } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -136082,9 +134377,9 @@ module.exports = class upbit extends Exchange { } else if ((locked !== undefined) && locked) { active = false; } - const maxOnetimeWithdrawal = this.safeFloat (withdrawLimits, 'onetime'); - const maxDailyWithdrawal = this.safeFloat (withdrawLimits, 'daily', maxOnetimeWithdrawal); - const remainingDailyWithdrawal = this.safeFloat (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); + const maxOnetimeWithdrawal = this.safeNumber (withdrawLimits, 'onetime'); + const maxDailyWithdrawal = this.safeNumber (withdrawLimits, 'daily', maxOnetimeWithdrawal); + const remainingDailyWithdrawal = this.safeNumber (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); let maxWithdrawLimit = undefined; if (remainingDailyWithdrawal > 0) { maxWithdrawLimit = remainingDailyWithdrawal; @@ -136100,11 +134395,11 @@ module.exports = class upbit extends Exchange { 'code': code, 'name': code, 'active': active, - 'fee': this.safeFloat (currencyInfo, 'withdraw_fee'), + 'fee': this.safeNumber (currencyInfo, 'withdraw_fee'), 'precision': precision, 'limits': { 'withdraw': { - 'min': this.safeFloat (withdrawLimits, 'minimum'), + 'min': this.safeNumber (withdrawLimits, 'minimum'), 'max': maxWithdrawLimit, }, }, @@ -136167,8 +134462,8 @@ module.exports = class upbit extends Exchange { }; const state = this.safeString (marketInfo, 'state'); const active = (state === 'active'); - const bidFee = this.safeFloat (response, 'bid_fee'); - const askFee = this.safeFloat (response, 'ask_fee'); + const bidFee = this.safeNumber (response, 'bid_fee'); + const askFee = this.safeNumber (response, 'ask_fee'); const fee = Math.max (bidFee, askFee); return { 'info': response, @@ -136184,7 +134479,7 @@ module.exports = class upbit extends Exchange { 'taker': fee, 'limits': { 'amount': { - 'min': this.safeFloat (ask, 'min_total'), + 'min': this.safeNumber (ask, 'min_total'), 'max': undefined, }, 'price': { @@ -136192,8 +134487,8 @@ module.exports = class upbit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (bid, 'min_total'), - 'max': this.safeFloat (marketInfo, 'max_total'), + 'min': this.safeNumber (bid, 'min_total'), + 'max': this.safeNumber (marketInfo, 'max_total'), }, }, }; @@ -136232,8 +134527,8 @@ module.exports = class upbit extends Exchange { 'price': 8, }; const active = true; - const makerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); - const takerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); + const makerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); + const takerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); result.push ({ 'id': id, 'symbol': symbol, @@ -136286,11 +134581,11 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { @@ -136393,30 +134688,30 @@ module.exports = class upbit extends Exchange { const timestamp = this.safeInteger (ticker, 'trade_timestamp'); const marketId = this.safeString2 (ticker, 'market', 'code'); const symbol = this.safeSymbol (marketId, market, '-'); - const previous = this.safeFloat (ticker, 'prev_closing_price'); - const last = this.safeFloat (ticker, 'trade_price'); - const change = this.safeFloat (ticker, 'signed_change_price'); - const percentage = this.safeFloat (ticker, 'signed_change_rate'); + const previous = this.safeNumber (ticker, 'prev_closing_price'); + const last = this.safeNumber (ticker, 'trade_price'); + const change = this.safeNumber (ticker, 'signed_change_price'); + const percentage = this.safeNumber (ticker, 'signed_change_rate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price'), - 'low': this.safeFloat (ticker, 'low_price'), + 'high': this.safeNumber (ticker, 'high_price'), + 'low': this.safeNumber (ticker, 'low_price'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'opening_price'), + 'open': this.safeNumber (ticker, 'opening_price'), 'close': last, 'last': last, 'previousClose': previous, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'acc_trade_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'acc_trade_price_24h'), + 'baseVolume': this.safeNumber (ticker, 'acc_trade_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'acc_trade_price_24h'), 'info': ticker, }; } @@ -136523,15 +134818,13 @@ module.exports = class upbit extends Exchange { } else if (askOrBid === 'bid') { side = 'buy'; } - let cost = this.safeFloat (trade, 'funds'); - const price = this.safeFloat2 (trade, 'trade_price', 'price'); - const amount = this.safeFloat2 (trade, 'trade_volume', 'volume'); + let cost = this.safeNumber (trade, 'funds'); + const priceString = this.safeString2 (trade, 'trade_price', 'price'); + const amountString = this.safeString2 (trade, 'trade_volume', 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString2 (trade, 'market', 'code'); market = this.safeMarket (marketId, market); @@ -136626,11 +134919,11 @@ module.exports = class upbit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'candle_date_time_utc')), - this.safeFloat (ohlcv, 'opening_price'), - this.safeFloat (ohlcv, 'high_price'), - this.safeFloat (ohlcv, 'low_price'), - this.safeFloat (ohlcv, 'trade_price'), - this.safeFloat (ohlcv, 'candle_acc_trade_volume'), // base volume + this.safeNumber (ohlcv, 'opening_price'), + this.safeNumber (ohlcv, 'high_price'), + this.safeNumber (ohlcv, 'low_price'), + this.safeNumber (ohlcv, 'trade_price'), + this.safeNumber (ohlcv, 'candle_acc_trade_volume'), // base volume ]; } @@ -136899,7 +135192,7 @@ module.exports = class upbit extends Exchange { // } // const id = this.safeString (transaction, 'uuid'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = undefined; // not present in the data structure received from the exchange const tag = undefined; // not present in the data structure received from the exchange const txid = this.safeString (transaction, 'txid'); @@ -136912,7 +135205,7 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -136997,10 +135290,10 @@ module.exports = class upbit extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const status = this.parseOrderStatus (this.safeString (order, 'state')); let lastTradeTimestamp = undefined; - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - const filled = this.safeFloat (order, 'executed_volume'); + let price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const filled = this.safeNumber (order, 'executed_volume'); let cost = undefined; if (type === 'price') { type = 'market'; @@ -137009,7 +135302,7 @@ module.exports = class upbit extends Exchange { } let average = undefined; let fee = undefined; - let feeCost = this.safeFloat (order, 'paid_fee'); + let feeCost = this.safeNumber (order, 'paid_fee'); const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); let trades = this.safeValue (order, 'trades', []); @@ -137032,7 +135325,7 @@ module.exports = class upbit extends Exchange { cost = this.sum (cost, trade['cost']); if (getFeesFromTrades) { const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); + const tradeFeeCost = this.safeNumber (tradeFee, 'cost'); if (tradeFeeCost !== undefined) { feeCost = this.sum (feeCost, tradeFeeCost); } @@ -137174,16 +135467,6 @@ module.exports = class upbit extends Exchange { return this.parseOrder (response); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetDepositsCoinAddresses (params); @@ -137381,212 +135664,7 @@ module.exports = class upbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],173:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); - -// --------------------------------------------------------------------------- - -module.exports = class vaultoro extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'vaultoro', - 'name': 'Vaultoro', - 'countries': [ 'CH' ], - 'rateLimit': 1000, - 'version': '1', - 'has': { - 'CORS': true, - 'fetchMarkets': true, - 'fetchOrderBook': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'fetchTrades': true, - 'fetchTicker': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg', - 'api': 'https://api.vaultoro.com', - 'www': 'https://www.vaultoro.com', - 'doc': 'https://api.vaultoro.com', - }, - 'commonCurrencies': { - 'GLD': 'Gold', - }, - 'api': { - 'public': { - 'get': [ - 'bidandask', - 'buyorders', - 'latest', - 'latesttrades', - 'markets', - 'orderbook', - 'sellorders', - 'transactions/day', - 'transactions/hour', - 'transactions/month', - ], - }, - 'private': { - 'get': [ - 'balance', - 'mytrades', - 'orders', - ], - 'post': [ - 'buy/{symbol}/{type}', - 'cancel/{id}', - 'sell/{symbol}/{type}', - 'withdraw', - ], - }, - }, - }); - } - - async fetchMarkets (params = {}) { - const result = []; - const response = await this.publicGetMarkets (params); - const market = this.safeValue (response, 'data'); - const baseId = this.safeString (market, 'MarketCurrency'); - const quoteId = this.safeString (market, 'BaseCurrency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const id = this.safeString (market, 'MarketName'); - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'active': undefined, - 'precision': this.precision, - 'limits': this.limits, - }); - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetBalance (params); - const balances = this.safeValue (response, 'data'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency_code'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'cash'); - account['used'] = this.safeFloat (balance, 'reserved'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetOrderbook (params); - const orderbook = { - 'bids': response['data'][0]['b'], - 'asks': response['data'][1]['s'], - }; - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'Gold_Price', 'Gold_Amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'Time')); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const price = this.safeFloat (trade, 'Gold_Price'); - const amount = this.safeFloat (trade, 'Gold_Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } - return { - 'id': undefined, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': undefined, - 'side': undefined, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const response = await this.publicGetTransactionsDay (params); - return this.parseTrades (response, market, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const method = 'privatePost' + this.capitalize (side) + 'SymbolType'; - const request = { - 'symbol': market['quoteId'].toLowerCase (), - 'type': type, - 'gld': amount, - 'price': price || 1, - }; - const response = await this[method] (this.extend (request, params)); - return { - 'info': response, - 'id': response['data']['Order_ID'], - }; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - return await this.privatePostCancelId (this.extend (request, params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/'; - if (api === 'public') { - url += path; - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce (); - url += this.version + '/' + this.implodeParams (path, params); - const query = this.extend ({ - 'nonce': nonce, - 'apikey': this.apiKey, - }, this.omit (params, this.extractParams (path))); - url += '?' + this.urlencode (query); - headers = { - 'Content-Type': 'application/json', - 'X-Signature': this.hmac (this.encode (url), this.encode (this.secret)), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } -}; - -},{"./base/Exchange":6}],174:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],170:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -137620,7 +135698,7 @@ module.exports = class vbtc extends foxbit { } }; -},{"./foxbit.js":87}],175:[function(require,module,exports){ +},{"./foxbit.js":85}],171:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -137628,6 +135706,7 @@ module.exports = class vbtc extends foxbit { const Exchange = require ('./base/Exchange'); const { ExchangeError, OrderNotFound, InvalidOrder, BadRequest, AuthenticationError, RateLimitExceeded, RequestTimeout, BadSymbol, AddressPending, PermissionDenied, InsufficientFunds } = require ('./base/errors'); const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -137819,15 +135898,15 @@ module.exports = class vcc extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, 'min'), + 'min': this.safeNumber (amountLimits, 'min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (priceLimits, 'min'), + 'min': this.safeNumber (priceLimits, 'min'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (costLimits, 'min'), + 'min': this.safeNumber (costLimits, 'min'), 'max': undefined, }, }, @@ -137874,12 +135953,12 @@ module.exports = class vcc extends Exchange { 'code': code, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': this.safeInteger (currency, 'decimal'), 'limits': { 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw'), - 'max': this.safeFloat (currency, 'max_withdraw'), + 'min': this.safeNumber (currency, 'min_withdraw'), + 'max': this.safeNumber (currency, 'max_withdraw'), }, }, }; @@ -137902,8 +135981,8 @@ module.exports = class vcc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } @@ -137929,11 +136008,11 @@ module.exports = class vcc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (data, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -137951,11 +136030,11 @@ module.exports = class vcc extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -138044,10 +136123,10 @@ module.exports = class vcc extends Exchange { // } // const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); - const open = this.safeFloat (ticker, 'open_price'); - const last = this.safeFloat (ticker, 'last_price'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); + const open = this.safeNumber (ticker, 'open_price'); + const last = this.safeNumber (ticker, 'last_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -138064,11 +136143,11 @@ module.exports = class vcc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -138182,17 +136261,17 @@ module.exports = class vcc extends Exchange { } market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'base_volume', 'quantity'); - let cost = this.safeFloat2 (trade, 'quote_volume', 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'base_volume', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber2 (trade, 'quote_volume', 'amount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const side = this.safeString2 (trade, 'type', 'trade_type'); const id = this.safeString2 (trade, 'trade_id', 'id'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -138377,7 +136456,7 @@ module.exports = class vcc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -138385,7 +136464,7 @@ module.exports = class vcc extends Exchange { const txid = this.safeString (transaction, 'transaction_id'); const tag = this.safeString (transaction, 'destination_tag'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -138630,46 +136709,27 @@ module.exports = class vcc extends Exchange { const marketId = baseId + '_' + quoteId; market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'executed_quantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - let cost = this.safeFloat (order, 'ceiling'); + const cost = this.safeNumber (order, 'ceiling'); const id = this.safeString (order, 'id'); - let average = undefined; - let price = this.safeFloat (order, 'price'); - // in case of market order - if (!price) { - price = this.safeFloat (order, 'executed_price'); - average = price; - } - let remaining = this.safeFloat (order, 'remaining'); - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if (filled !== undefined) { - if ((amount !== undefined) && (remaining === undefined)) { - remaining = Math.max (0, amount - filled); - } - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((average === undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'executed_price'); + const remaining = this.safeNumber (order, 'remaining'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'trade_type'); const fee = { 'currency': market['quote'], - 'cost': this.safeFloat (order, 'fee'), - 'rate': this.safeFloat (order, 'fee_rate'), + 'cost': this.safeNumber (order, 'fee'), + 'rate': this.safeNumber (order, 'fee_rate'), }; let lastTradeTimestamp = undefined; if (updated !== created) { lastTradeTimestamp = updated; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': id, 'timestamp': created, @@ -138691,7 +136751,7 @@ module.exports = class vcc extends Exchange { 'fee': fee, 'trades': undefined, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -138961,7 +137021,7 @@ module.exports = class vcc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],176:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],172:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -139529,13 +137589,13 @@ module.exports = class wavesexchange extends Exchange { symbol = market['symbol']; } const data = this.safeValue (ticker, 'data', {}); - const last = this.safeFloat (data, 'lastPrice'); - const low = this.safeFloat (data, 'low'); - const high = this.safeFloat (data, 'high'); - const vwap = this.safeFloat (data, 'weightedAveragePrice'); - const baseVolume = this.safeFloat (data, 'volume'); - const quoteVolume = this.safeFloat (data, 'quoteVolume'); - const open = this.safeValue (data, 'firstPrice'); + const last = this.safeNumber (data, 'lastPrice'); + const low = this.safeNumber (data, 'low'); + const high = this.safeNumber (data, 'high'); + const vwap = this.safeNumber (data, 'weightedAveragePrice'); + const baseVolume = this.safeNumber (data, 'volume'); + const quoteVolume = this.safeNumber (data, 'quoteVolume'); + const open = this.safeNumber (data, 'firstPrice'); let change = undefined; let average = undefined; let percentage = undefined; @@ -139689,11 +137749,11 @@ module.exports = class wavesexchange extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.parse8601 (this.safeString (data, 'time')), - this.safeFloat (data, 'open'), - this.safeFloat (data, 'high'), - this.safeFloat (data, 'low'), - this.safeFloat (data, 'close'), - this.safeFloat (data, 'volume', 0), + this.safeNumber (data, 'open'), + this.safeNumber (data, 'high'), + this.safeNumber (data, 'low'), + this.safeNumber (data, 'close'), + this.safeNumber (data, 'volume', 0), ]; } @@ -139908,7 +137968,7 @@ module.exports = class wavesexchange extends Exchange { } if (matcherFee === undefined) { const wavesPrecision = this.safeInteger (this.options, 'wavesPrecision', 8); - const rate = this.safeFloat (rates, matcherFeeAssetId); + const rate = this.safeNumber (rates, matcherFeeAssetId); const code = this.safeCurrencyCode (matcherFeeAssetId); const currency = this.currency (code); const newPrecison = Math.pow (10, wavesPrecision - currency['precision']); @@ -140318,7 +138378,7 @@ module.exports = class wavesexchange extends Exchange { const issueTransaction = this.safeValue (entry, 'issueTransaction'); const decimals = this.safeInteger (issueTransaction, 'decimals'); const currencyId = this.safeString (entry, 'assetId'); - const balance = this.safeFloat (entry, 'balance'); + const balance = this.safeNumber (entry, 'balance'); let code = undefined; if (currencyId in this.currencies_by_id) { code = this.safeCurrencyCode (currencyId); @@ -140348,7 +138408,7 @@ module.exports = class wavesexchange extends Exchange { if (!(code in result)) { result[code] = this.account (); } - const amount = this.safeFloat (reservedBalance, currencyId); + const amount = this.safeNumber (reservedBalance, currencyId); result[code]['used'] = this.currencyFromPrecision (code, amount); } const wavesRequest = { @@ -140361,7 +138421,7 @@ module.exports = class wavesexchange extends Exchange { // "balance": 909085978 // } result['WAVES'] = this.safeValue (result, 'WAVES', {}); - result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeFloat (wavesTotal, 'balance')); + result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeNumber (wavesTotal, 'balance')); const codes = Object.keys (result); for (let i = 0; i < codes.length; i++) { const code = codes[i]; @@ -140453,8 +138513,8 @@ module.exports = class wavesexchange extends Exchange { const datetime = this.safeString (data, 'timestamp'); const timestamp = this.parse8601 (datetime); const id = this.safeString (data, 'id'); - const price = this.safeFloat (data, 'price'); - const amount = this.safeFloat (data, 'amount'); + const price = this.safeNumber (data, 'price'); + const amount = this.safeNumber (data, 'amount'); const order1 = this.safeValue (data, 'order1'); const order2 = this.safeValue (data, 'order2'); let order = undefined; @@ -140478,7 +138538,7 @@ module.exports = class wavesexchange extends Exchange { cost = price * amount; } const fee = { - 'cost': this.safeFloat (data, 'fee'), + 'cost': this.safeNumber (data, 'fee'), 'currency': this.safeCurrencyCode (this.safeString (order, 'matcherFeeAssetId', 'WAVES')), }; return { @@ -140560,7 +138620,7 @@ module.exports = class wavesexchange extends Exchange { const withdrawAddress = await this.privateGetWithdrawAddressesCurrencyAddress (withdrawAddressRequest); const currency = this.safeValue (withdrawAddress, 'currency'); const allowedAmount = this.safeValue (currency, 'allowed_amount'); - const minimum = this.safeFloat (allowedAmount, 'min'); + const minimum = this.safeNumber (allowedAmount, 'min'); if (amount <= minimum) { throw new BadRequest (this.id + ' ' + code + ' withdraw failed, amount ' + amount.toString () + ' must be greater than the minimum allowed amount of ' + minimum.toString ()); } @@ -140630,13 +138690,14 @@ module.exports = class wavesexchange extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],177:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],173:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeNotAvailable, ExchangeError, DDoSProtection, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -140797,7 +138858,7 @@ module.exports = class whitebit extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -140805,7 +138866,7 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minTotal'), + 'min': this.safeNumber (market, 'minTotal'), 'max': undefined, }, }, @@ -140870,8 +138931,8 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -140883,8 +138944,8 @@ module.exports = class whitebit extends Exchange { const response = await this.publicV2GetFee (params); const fees = this.safeValue (response, 'result'); return { - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), }; } @@ -140954,8 +139015,8 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let change = undefined; if (percentage !== undefined) { change = this.numberToString (percentage * 0.01); @@ -140964,22 +139025,22 @@ module.exports = class whitebit extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'deal'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'deal'), 'info': ticker, }; } @@ -141147,8 +139208,11 @@ module.exports = class whitebit extends Exchange { } else { timestamp = parseInt (timestamp * 1000); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'volume'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'volume'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const id = this.safeString2 (trade, 'id', 'tradeId'); let side = this.safeString (trade, 'type'); if (side === undefined) { @@ -141159,10 +139223,6 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined && price !== undefined) { - cost = amount * price; - } return { 'info': trade, 'timestamp': timestamp, @@ -141232,11 +139292,11 @@ module.exports = class whitebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -141285,7 +139345,7 @@ module.exports = class whitebit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],178:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],174:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -141440,14 +139500,13 @@ module.exports = class xbtce extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'FreeAmount'), - 'used': this.safeFloat (balance, 'LockedAmount'), - 'total': this.safeFloat (balance, 'Amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'FreeAmount'); + account['used'] = this.safeString (balance, 'LockedAmount'); + account['total'] = this.safeString (balance, 'Amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -141559,11 +139618,11 @@ module.exports = class xbtce extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeInteger (ohlcv, 'Timestamp'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -141657,11 +139716,12 @@ module.exports = class xbtce extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],179:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],175:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, InsufficientFunds, InvalidAddress, BadSymbol, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class xena extends Exchange { describe () { @@ -141937,8 +139997,8 @@ module.exports = class xena extends Exchange { 'price': pricePrecision, 'amount': 0, }; - const maxCost = this.safeFloat (market, 'maxOrderQty'); - const minCost = this.safeFloat (market, 'minOrderQuantity'); + const maxCost = this.safeNumber (market, 'maxOrderQty'); + const minCost = this.safeNumber (market, 'minOrderQuantity'); const limits = { 'amount': { 'min': undefined, @@ -142023,7 +140083,7 @@ module.exports = class xena extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (withdraw, 'commission'), + 'fee': this.safeNumber (withdraw, 'commission'), 'precision': precision, 'limits': { 'amount': { @@ -142039,7 +140099,7 @@ module.exports = class xena extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'minAmount'), + 'min': this.safeNumber (withdraw, 'minAmount'), 'max': undefined, }, }, @@ -142067,8 +140127,8 @@ module.exports = class xena extends Exchange { const timestamp = this.milliseconds (); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPx'); - const open = this.safeFloat (ticker, 'firstPx'); + const last = this.safeNumber (ticker, 'lastPx'); + const open = this.safeNumber (ticker, 'firstPx'); let percentage = undefined; let change = undefined; let average = undefined; @@ -142079,18 +140139,18 @@ module.exports = class xena extends Exchange { percentage = change / open * 100; } } - const buyVolume = this.safeFloat (ticker, 'buyVolume'); - const sellVolume = this.safeFloat (ticker, 'sellVolume'); + const buyVolume = this.safeNumber (ticker, 'buyVolume'); + const sellVolume = this.safeNumber (ticker, 'sellVolume'); const baseVolume = this.sum (buyVolume, sellVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPx'), - 'low': this.safeFloat (ticker, 'lowPx'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'highPx'), + 'low': this.safeNumber (ticker, 'lowPx'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -142267,11 +140327,11 @@ module.exports = class xena extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onHold'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onHold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTrade (trade, market = undefined) { @@ -142325,20 +140385,17 @@ module.exports = class xena extends Exchange { const orderId = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat2 (trade, 'lastPx', 'mdEntryPx'); - const amount = this.safeFloat2 (trade, 'lastQty', 'mdEntrySize'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'lastPx', 'mdEntryPx'); + const amountString = this.safeString2 (trade, 'lastQty', 'mdEntrySize'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (trade, 'commRate'); + const feeRate = this.safeNumber (trade, 'commRate'); fee = { 'cost': feeCost, 'rate': feeRate, @@ -142453,15 +140510,15 @@ module.exports = class xena extends Exchange { // const transactTime = this.safeInteger (ohlcv, 'transactTime'); const timestamp = parseInt (transactTime / 1000000); - const buyVolume = this.safeFloat (ohlcv, 'buyVolume'); - const sellVolume = this.safeFloat (ohlcv, 'sellVolume'); + const buyVolume = this.safeNumber (ohlcv, 'buyVolume'); + const sellVolume = this.safeNumber (ohlcv, 'sellVolume'); const volume = this.sum (buyVolume, sellVolume); return [ timestamp, - this.safeFloat (ohlcv, 'firstPx'), - this.safeFloat (ohlcv, 'highPx'), - this.safeFloat (ohlcv, 'lowPx'), - this.safeFloat (ohlcv, 'lastPx'), + this.safeNumber (ohlcv, 'firstPx'), + this.safeNumber (ohlcv, 'highPx'), + this.safeNumber (ohlcv, 'lowPx'), + this.safeNumber (ohlcv, 'lastPx'), volume, ]; } @@ -142586,11 +140643,10 @@ module.exports = class xena extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); - let cost = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); let side = this.safeStringLower (order, 'side'); if (side === '1') { side = 'buy'; @@ -142607,12 +140663,7 @@ module.exports = class xena extends Exchange { } else if (type === '4') { type = 'stop-limit'; } - if (cost === undefined) { - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -142627,14 +140678,14 @@ module.exports = class xena extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -142687,7 +140738,7 @@ module.exports = class xena extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if ((type === 'stop') || (type === 'stop-limit')) { - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPx param for order type ' + type); } @@ -142766,12 +140817,12 @@ module.exports = class xena extends Exchange { if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); } - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx !== undefined) { request['stopPx'] = this.priceToPrecision (symbol, stopPx); params = this.omit (params, 'stopPx'); } - const capPrice = this.safeFloat (params, 'capPrice'); + const capPrice = this.safeNumber (params, 'capPrice'); if (capPrice !== undefined) { request['capPrice'] = this.priceToPrecision (symbol, capPrice); params = this.omit (params, 'capPrice'); @@ -143126,7 +141177,7 @@ module.exports = class xena extends Exchange { const address = this.safeString (transaction, 'address'); const addressFrom = undefined; const addressTo = address; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const fee = undefined; return { @@ -143223,7 +141274,7 @@ module.exports = class xena extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'kind')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); @@ -143235,11 +141286,11 @@ module.exports = class xena extends Exchange { timestamp = parseInt (timestamp / 1000000); } const fee = { - 'cost': this.safeFloat (item, 'commission'), + 'cost': this.safeNumber (item, 'commission'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -143379,13 +141430,14 @@ module.exports = class xena extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],180:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],176:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError, RateLimitExceeded } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -143520,6 +141572,7 @@ module.exports = class yobit extends Exchange { 'NAV': 'NavajoCoin', 'NBT': 'NiceBytes', 'OMG': 'OMGame', + 'ONX': 'Onix', 'PAC': '$PAC', 'PLAY': 'PlayCoin', 'PIVX': 'Darknet', @@ -143618,15 +141671,33 @@ module.exports = class yobit extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['total'] = this.safeFloat (total, currencyId); + account['free'] = this.safeString (free, currencyId); + account['total'] = this.safeString (total, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615856752, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":10000, + // "min_amount":0.0001, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.2, + // "fee_buyer":0.2, + // "fee_seller":0.2 + // }, + // }, + // } + // const markets = this.safeValue (response, 'pairs'); const keys = Object.keys (markets); const result = []; @@ -143644,15 +141715,15 @@ module.exports = class yobit extends Exchange { 'price': this.safeInteger (market, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }; const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }; const costLimits = { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }; const limits = { 'amount': amountLimits, @@ -143661,6 +141732,7 @@ module.exports = class yobit extends Exchange { }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -143669,7 +141741,7 @@ module.exports = class yobit extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -143745,16 +141817,16 @@ module.exports = class yobit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -143763,9 +141835,9 @@ module.exports = class yobit extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -143814,15 +141886,18 @@ module.exports = class yobit extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const order = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const type = 'limit'; // all trades are still limit trades let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -143837,12 +141912,6 @@ module.exports = class yobit extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, 'taker'); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': order, @@ -143904,8 +141973,8 @@ module.exports = class yobit extends Exchange { id = this.safeString (response['return'], 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (response['return'], 'received', 0.0); + remaining = this.safeNumber (response['return'], 'remains', amount); } const timestamp = this.milliseconds (); return { @@ -143955,21 +142024,13 @@ module.exports = class yobit extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp_created'); const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const remaining = this.safeFloat (order, 'amount'); - const amount = this.safeFloat (order, 'start_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - cost = price * filled; - } - } + const remaining = this.safeNumber (order, 'amount'); + const amount = this.safeNumber (order, 'start_amount'); + const price = this.safeNumber (order, 'rate'); const fee = undefined; const type = 'limit'; const side = this.safeString (order, 'type'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -143983,16 +142044,15 @@ module.exports = class yobit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -144203,13 +142263,14 @@ module.exports = class yobit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],181:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],177:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -144333,6 +142394,27 @@ module.exports = class zaif extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetCurrencyPairsAll (params); + // + // [ + // { + // "aux_unit_point": 0, + // "item_japanese": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3", + // "aux_unit_step": 5.0, + // "description": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3\u30fb\u65e5\u672c\u5186\u306e\u53d6\u5f15\u3092\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059", + // "item_unit_min": 0.001, + // "event_number": 0, + // "currency_pair": "btc_jpy", + // "is_token": false, + // "aux_unit_min": 5.0, + // "aux_japanese": "\u65e5\u672c\u5186", + // "id": 1, + // "item_unit_step": 0.0001, + // "name": "BTC/JPY", + // "seq": 0, + // "title": "BTC/JPY" + // } + // ] + // const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -144343,8 +142425,8 @@ module.exports = class zaif extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': -Math.log10 (market['item_unit_step']), - 'price': market['aux_unit_point'], + 'amount': -Math.log10 (this.safeNumber (market, 'item_unit_step')), + 'price': this.safeInteger (market, 'aux_unit_point'), }; const fees = this.safeValue (this.options['fees'], symbol, this.fees['trading']); const taker = fees['taker']; @@ -144362,11 +142444,11 @@ module.exports = class zaif extends Exchange { 'maker': maker, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'item_unit_min'), + 'min': this.safeNumber (market, 'item_unit_min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'aux_unit_min'), + 'min': this.safeNumber (market, 'aux_unit_min'), 'max': undefined, }, 'cost': { @@ -144398,7 +142480,7 @@ module.exports = class zaif extends Exchange { }; if ('deposit' in balances) { if (currencyId in balances['deposit']) { - account['total'] = this.safeFloat (balances['deposit'], currencyId); + account['total'] = this.safeNumber (balances['deposit'], currencyId); account['used'] = account['total'] - account['free']; } } @@ -144423,22 +142505,22 @@ module.exports = class zaif extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.milliseconds (); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -144459,14 +142541,11 @@ module.exports = class zaif extends Exchange { side = (side === 'bid') ? 'buy' : 'sell'; const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString2 (trade, 'id', 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); return { @@ -144544,16 +142623,10 @@ module.exports = class zaif extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp'); const marketId = this.safeString (order, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -144567,7 +142640,7 @@ module.exports = class zaif extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': undefined, 'remaining': undefined, @@ -144575,7 +142648,7 @@ module.exports = class zaif extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -144694,13 +142767,14 @@ module.exports = class zaif extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],182:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],178:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadRequest, ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, OrderNotFound, ExchangeNotAvailable, DDoSProtection, InvalidOrder, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -144786,8 +142860,8 @@ module.exports = class zb extends Exchange { 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg', 'api': { - 'public': 'http://api.zb.cn/data', // no https for public API - 'private': 'https://trade.zb.cn/api', + 'public': 'https://api.zb.today/data', + 'private': 'https://trade.zb.today/api', }, 'www': 'https://www.zb.com', 'doc': 'https://www.zb.com/i/developer', @@ -144902,6 +142976,16 @@ module.exports = class zb extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetMarkets (params); + // + // { + // "zb_qc":{ + // "amountScale":2, + // "minAmount":0.01, + // "minSize":5, + // "priceScale":4, + // }, + // } + // const keys = Object.keys (markets); const result = []; for (let i = 0; i < keys.length; i++) { @@ -144965,11 +143049,11 @@ module.exports = class zb extends Exchange { const account = this.account (); const currencyId = this.safeString (balance, 'key'); const code = this.safeCurrencyCode (currencyId); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'freez'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'freez'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -145018,18 +143102,6 @@ module.exports = class zb extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetGetPayinAddress (params); @@ -145136,16 +143208,16 @@ module.exports = class zb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -145155,12 +143227,23 @@ module.exports = class zb extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; } + parseOHLCV (ohlcv, market = undefined) { + return [ + this.safeInteger (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + ]; + } + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -145185,14 +143268,12 @@ module.exports = class zb extends Exchange { let side = this.safeString (trade, 'trade_type'); side = (side === 'bid') ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const costString = Precise.stringMul (priceString, amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (costString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -145371,23 +143452,13 @@ module.exports = class zb extends Exchange { const timestamp = this.safeInteger (order, 'trade_date'); const marketId = this.safeString (order, 'currency'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'trade_amount'); - const amount = this.safeFloat (order, 'total_amount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'trade_money'); - let average = undefined; + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'trade_amount'); + const amount = this.safeNumber (order, 'total_amount'); + const cost = this.safeNumber (order, 'trade_money'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((cost !== undefined) && (filled !== undefined) && (filled > 0)) { - average = cost / filled; - } const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fees'); + const feeCost = this.safeNumber (order, 'fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -145402,7 +143473,7 @@ module.exports = class zb extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -145416,15 +143487,15 @@ module.exports = class zb extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -145487,7 +143558,7 @@ module.exports = class zb extends Exchange { // const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'hash'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let timestamp = this.parse8601 (this.safeString (transaction, 'submit_time')); timestamp = this.safeInteger (transaction, 'submitTime', timestamp); let address = this.safeString2 (transaction, 'toAddress', 'address'); @@ -145507,7 +143578,7 @@ module.exports = class zb extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -145540,7 +143611,7 @@ module.exports = class zb extends Exchange { if (password === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires exchange.password or a safePwd parameter'); } - const fees = this.safeFloat (params, 'fees'); + const fees = this.safeNumber (params, 'fees'); if (fees === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires a fees parameter'); } @@ -145731,7 +143802,7 @@ module.exports = class zb extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],183:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],179:[function(require,module,exports){ (function (global){ 'use strict'; @@ -146225,7 +144296,7 @@ var objectKeys = Object.keys || function (obj) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"util/":241}],184:[function(require,module,exports){ +},{"util/":237}],180:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength @@ -146341,9 +144412,9 @@ function fromByteArray (uint8) { return parts.join('') } -},{}],185:[function(require,module,exports){ +},{}],181:[function(require,module,exports){ -},{}],186:[function(require,module,exports){ +},{}],182:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; /* eslint camelcase: "off" */ @@ -146755,7 +144826,7 @@ Zlib.prototype._reset = function () { exports.Zlib = Zlib; }).call(this,require('_process'),require("buffer").Buffer) -},{"_process":210,"assert":183,"buffer":188,"pako/lib/zlib/constants":200,"pako/lib/zlib/deflate.js":202,"pako/lib/zlib/inflate.js":204,"pako/lib/zlib/zstream":208}],187:[function(require,module,exports){ +},{"_process":206,"assert":179,"buffer":184,"pako/lib/zlib/constants":196,"pako/lib/zlib/deflate.js":198,"pako/lib/zlib/inflate.js":200,"pako/lib/zlib/zstream":204}],183:[function(require,module,exports){ (function (process){ 'use strict'; @@ -147367,7 +145438,7 @@ util.inherits(DeflateRaw, Zlib); util.inherits(InflateRaw, Zlib); util.inherits(Unzip, Zlib); }).call(this,require('_process')) -},{"./binding":186,"_process":210,"assert":183,"buffer":188,"stream":229,"util":241}],188:[function(require,module,exports){ +},{"./binding":182,"_process":206,"assert":179,"buffer":184,"stream":225,"util":237}],184:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -149083,7 +147154,7 @@ function numberIsNaN (obj) { return obj !== obj // eslint-disable-line no-self-compare } -},{"base64-js":184,"ieee754":194}],189:[function(require,module,exports){ +},{"base64-js":180,"ieee754":190}],185:[function(require,module,exports){ module.exports = { "100": "Continue", "101": "Switching Protocols", @@ -149149,7 +147220,7 @@ module.exports = { "511": "Network Authentication Required" } -},{}],190:[function(require,module,exports){ +},{}],186:[function(require,module,exports){ module.exports={ "O_RDONLY": 0, "O_WRONLY": 1, @@ -149360,7 +147431,7 @@ module.exports={ "UV_UDP_REUSEADDR": 4 } -},{}],191:[function(require,module,exports){ +},{}],187:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -149471,7 +147542,7 @@ function objectToString(o) { } }).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":196}],192:[function(require,module,exports){ +},{"../../is-buffer/index.js":192}],188:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -149775,7 +147846,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],193:[function(require,module,exports){ +},{}],189:[function(require,module,exports){ var http = require('http') var url = require('url') @@ -149808,7 +147879,7 @@ function validateParams (params) { return params } -},{"http":230,"url":236}],194:[function(require,module,exports){ +},{"http":226,"url":232}],190:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -149894,7 +147965,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],195:[function(require,module,exports){ +},{}],191:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -149919,7 +147990,7 @@ if (typeof Object.create === 'function') { } } -},{}],196:[function(require,module,exports){ +},{}],192:[function(require,module,exports){ /*! * Determine if an object is a Buffer * @@ -149942,14 +148013,14 @@ function isSlowBuffer (obj) { return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) } -},{}],197:[function(require,module,exports){ +},{}],193:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],198:[function(require,module,exports){ +},{}],194:[function(require,module,exports){ 'use strict'; @@ -150056,7 +148127,7 @@ exports.setTyped = function (on) { exports.setTyped(TYPED_OK); -},{}],199:[function(require,module,exports){ +},{}],195:[function(require,module,exports){ 'use strict'; // Note: adler32 takes 12% for level 0 and 2% for level 6. @@ -150109,7 +148180,7 @@ function adler32(adler, buf, len, pos) { module.exports = adler32; -},{}],200:[function(require,module,exports){ +},{}],196:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -150179,7 +148250,7 @@ module.exports = { //Z_NULL: null // Use -1 or null inline, depending on var type }; -},{}],201:[function(require,module,exports){ +},{}],197:[function(require,module,exports){ 'use strict'; // Note: we can't get significant speed boost here. @@ -150240,7 +148311,7 @@ function crc32(crc, buf, len, pos) { module.exports = crc32; -},{}],202:[function(require,module,exports){ +},{}],198:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -152116,7 +150187,7 @@ exports.deflatePrime = deflatePrime; exports.deflateTune = deflateTune; */ -},{"../utils/common":198,"./adler32":199,"./crc32":201,"./messages":206,"./trees":207}],203:[function(require,module,exports){ +},{"../utils/common":194,"./adler32":195,"./crc32":197,"./messages":202,"./trees":203}],199:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -152463,7 +150534,7 @@ module.exports = function inflate_fast(strm, start) { return; }; -},{}],204:[function(require,module,exports){ +},{}],200:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154021,7 +152092,7 @@ exports.inflateSyncPoint = inflateSyncPoint; exports.inflateUndermine = inflateUndermine; */ -},{"../utils/common":198,"./adler32":199,"./crc32":201,"./inffast":203,"./inftrees":205}],205:[function(require,module,exports){ +},{"../utils/common":194,"./adler32":195,"./crc32":197,"./inffast":199,"./inftrees":201}],201:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154366,7 +152437,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 0; }; -},{"../utils/common":198}],206:[function(require,module,exports){ +},{"../utils/common":194}],202:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154400,7 +152471,7 @@ module.exports = { '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ }; -},{}],207:[function(require,module,exports){ +},{}],203:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -155622,7 +153693,7 @@ exports._tr_flush_block = _tr_flush_block; exports._tr_tally = _tr_tally; exports._tr_align = _tr_align; -},{"../utils/common":198}],208:[function(require,module,exports){ +},{"../utils/common":194}],204:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -155671,7 +153742,7 @@ function ZStream() { module.exports = ZStream; -},{}],209:[function(require,module,exports){ +},{}],205:[function(require,module,exports){ (function (process){ 'use strict'; @@ -155718,7 +153789,7 @@ function nextTick(fn, arg1, arg2, arg3) { } }).call(this,require('_process')) -},{"_process":210}],210:[function(require,module,exports){ +},{"_process":206}],206:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -155904,7 +153975,7 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],211:[function(require,module,exports){ +},{}],207:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.1 by @mathias */ ;(function(root) { @@ -156441,7 +154512,7 @@ process.umask = function() { return 0; }; }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],212:[function(require,module,exports){ +},{}],208:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156527,7 +154598,7 @@ var isArray = Array.isArray || function (xs) { return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],213:[function(require,module,exports){ +},{}],209:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156614,16 +154685,16 @@ var objectKeys = Object.keys || function (obj) { return res; }; -},{}],214:[function(require,module,exports){ +},{}],210:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":212,"./encode":213}],215:[function(require,module,exports){ +},{"./decode":208,"./encode":209}],211:[function(require,module,exports){ module.exports = require('./lib/_stream_duplex.js'); -},{"./lib/_stream_duplex.js":216}],216:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":212}],212:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156748,7 +154819,7 @@ function forEach(xs, f) { f(xs[i], i); } } -},{"./_stream_readable":218,"./_stream_writable":220,"core-util-is":191,"inherits":195,"process-nextick-args":209}],217:[function(require,module,exports){ +},{"./_stream_readable":214,"./_stream_writable":216,"core-util-is":187,"inherits":191,"process-nextick-args":205}],213:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156796,7 +154867,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":219,"core-util-is":191,"inherits":195}],218:[function(require,module,exports){ +},{"./_stream_transform":215,"core-util-is":187,"inherits":191}],214:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -157806,7 +155877,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./_stream_duplex":216,"./internal/streams/BufferList":221,"./internal/streams/destroy":222,"./internal/streams/stream":223,"_process":210,"core-util-is":191,"events":192,"inherits":195,"isarray":197,"process-nextick-args":209,"safe-buffer":228,"string_decoder/":234,"util":185}],219:[function(require,module,exports){ +},{"./_stream_duplex":212,"./internal/streams/BufferList":217,"./internal/streams/destroy":218,"./internal/streams/stream":219,"_process":206,"core-util-is":187,"events":188,"inherits":191,"isarray":193,"process-nextick-args":205,"safe-buffer":224,"string_decoder/":230,"util":181}],215:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -158021,7 +156092,7 @@ function done(stream, er, data) { return stream.push(null); } -},{"./_stream_duplex":216,"core-util-is":191,"inherits":195}],220:[function(require,module,exports){ +},{"./_stream_duplex":212,"core-util-is":187,"inherits":191}],216:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -158688,7 +156759,7 @@ Writable.prototype._destroy = function (err, cb) { cb(err); }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./_stream_duplex":216,"./internal/streams/destroy":222,"./internal/streams/stream":223,"_process":210,"core-util-is":191,"inherits":195,"process-nextick-args":209,"safe-buffer":228,"util-deprecate":238}],221:[function(require,module,exports){ +},{"./_stream_duplex":212,"./internal/streams/destroy":218,"./internal/streams/stream":219,"_process":206,"core-util-is":187,"inherits":191,"process-nextick-args":205,"safe-buffer":224,"util-deprecate":234}],217:[function(require,module,exports){ 'use strict'; /**/ @@ -158763,7 +156834,7 @@ module.exports = function () { return BufferList; }(); -},{"safe-buffer":228}],222:[function(require,module,exports){ +},{"safe-buffer":224}],218:[function(require,module,exports){ 'use strict'; /**/ @@ -158836,13 +156907,13 @@ module.exports = { destroy: destroy, undestroy: undestroy }; -},{"process-nextick-args":209}],223:[function(require,module,exports){ +},{"process-nextick-args":205}],219:[function(require,module,exports){ module.exports = require('events').EventEmitter; -},{"events":192}],224:[function(require,module,exports){ +},{"events":188}],220:[function(require,module,exports){ module.exports = require('./readable').PassThrough -},{"./readable":225}],225:[function(require,module,exports){ +},{"./readable":221}],221:[function(require,module,exports){ exports = module.exports = require('./lib/_stream_readable.js'); exports.Stream = exports; exports.Readable = exports; @@ -158851,13 +156922,13 @@ exports.Duplex = require('./lib/_stream_duplex.js'); exports.Transform = require('./lib/_stream_transform.js'); exports.PassThrough = require('./lib/_stream_passthrough.js'); -},{"./lib/_stream_duplex.js":216,"./lib/_stream_passthrough.js":217,"./lib/_stream_readable.js":218,"./lib/_stream_transform.js":219,"./lib/_stream_writable.js":220}],226:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":212,"./lib/_stream_passthrough.js":213,"./lib/_stream_readable.js":214,"./lib/_stream_transform.js":215,"./lib/_stream_writable.js":216}],222:[function(require,module,exports){ module.exports = require('./readable').Transform -},{"./readable":225}],227:[function(require,module,exports){ +},{"./readable":221}],223:[function(require,module,exports){ module.exports = require('./lib/_stream_writable.js'); -},{"./lib/_stream_writable.js":220}],228:[function(require,module,exports){ +},{"./lib/_stream_writable.js":216}],224:[function(require,module,exports){ /* eslint-disable node/no-deprecated-api */ var buffer = require('buffer') var Buffer = buffer.Buffer @@ -158921,7 +156992,7 @@ SafeBuffer.allocUnsafeSlow = function (size) { return buffer.SlowBuffer(size) } -},{"buffer":188}],229:[function(require,module,exports){ +},{"buffer":184}],225:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -159050,7 +157121,7 @@ Stream.prototype.pipe = function(dest, options) { return dest; }; -},{"events":192,"inherits":195,"readable-stream/duplex.js":215,"readable-stream/passthrough.js":224,"readable-stream/readable.js":225,"readable-stream/transform.js":226,"readable-stream/writable.js":227}],230:[function(require,module,exports){ +},{"events":188,"inherits":191,"readable-stream/duplex.js":211,"readable-stream/passthrough.js":220,"readable-stream/readable.js":221,"readable-stream/transform.js":222,"readable-stream/writable.js":223}],226:[function(require,module,exports){ (function (global){ var ClientRequest = require('./lib/request') var extend = require('xtend') @@ -159132,7 +157203,7 @@ http.METHODS = [ 'UNSUBSCRIBE' ] }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./lib/request":232,"builtin-status-codes":189,"url":236,"xtend":242}],231:[function(require,module,exports){ +},{"./lib/request":228,"builtin-status-codes":185,"url":232,"xtend":238}],227:[function(require,module,exports){ (function (global){ exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream) @@ -159205,7 +157276,7 @@ function isFunction (value) { xhr = null // Help gc }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],232:[function(require,module,exports){ +},{}],228:[function(require,module,exports){ (function (process,global,Buffer){ var capability = require('./capability') var inherits = require('inherits') @@ -159515,7 +157586,7 @@ var unsafeHeaders = [ ] }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"./capability":231,"./response":233,"_process":210,"buffer":188,"inherits":195,"readable-stream":225,"to-arraybuffer":235}],233:[function(require,module,exports){ +},{"./capability":227,"./response":229,"_process":206,"buffer":184,"inherits":191,"readable-stream":221,"to-arraybuffer":231}],229:[function(require,module,exports){ (function (process,global,Buffer){ var capability = require('./capability') var inherits = require('inherits') @@ -159701,7 +157772,7 @@ IncomingMessage.prototype._onXHRProgress = function () { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"./capability":231,"_process":210,"buffer":188,"inherits":195,"readable-stream":225}],234:[function(require,module,exports){ +},{"./capability":227,"_process":206,"buffer":184,"inherits":191,"readable-stream":221}],230:[function(require,module,exports){ 'use strict'; var Buffer = require('safe-buffer').Buffer; @@ -159974,7 +158045,7 @@ function simpleWrite(buf) { function simpleEnd(buf) { return buf && buf.length ? this.write(buf) : ''; } -},{"safe-buffer":228}],235:[function(require,module,exports){ +},{"safe-buffer":224}],231:[function(require,module,exports){ var Buffer = require('buffer').Buffer module.exports = function (buf) { @@ -160003,7 +158074,7 @@ module.exports = function (buf) { } } -},{"buffer":188}],236:[function(require,module,exports){ +},{"buffer":184}],232:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -160737,7 +158808,7 @@ Url.prototype.parseHost = function() { if (host) this.hostname = host; }; -},{"./util":237,"punycode":211,"querystring":214}],237:[function(require,module,exports){ +},{"./util":233,"punycode":207,"querystring":210}],233:[function(require,module,exports){ 'use strict'; module.exports = { @@ -160755,7 +158826,7 @@ module.exports = { } }; -},{}],238:[function(require,module,exports){ +},{}],234:[function(require,module,exports){ (function (global){ /** @@ -160826,16 +158897,16 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],239:[function(require,module,exports){ -arguments[4][195][0].apply(exports,arguments) -},{"dup":195}],240:[function(require,module,exports){ +},{}],235:[function(require,module,exports){ +arguments[4][191][0].apply(exports,arguments) +},{"dup":191}],236:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],241:[function(require,module,exports){ +},{}],237:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -161425,7 +159496,7 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":240,"_process":210,"inherits":239}],242:[function(require,module,exports){ +},{"./support/isBuffer":236,"_process":206,"inherits":235}],238:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aax.js index 9c71e445f..3b8be7dc2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, ExchangeNotAvailable, OrderNotFound, InvalidOrder, CancelPending, RateLimitExceeded, InsufficientFunds, BadRequest, BadSymbol, PermissionDenied } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -35,6 +36,7 @@ module.exports = class aax extends Exchange { 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, + 'fetchStatus': true, 'fetchTicker': 'emulated', 'fetchTickers': true, 'fetchTrades': true, @@ -233,6 +235,37 @@ module.exports = class aax extends Exchange { }); } + async fetchStatus (params = {}) { + const response = await this.publicGetAnnouncementMaintenance (params); + // + // { + // "code": 1, + // "data": { + // "startTime":"2020-06-25T02:15:00.000Z", + // "endTime":"2020-06-25T02:45:00.000Z", + // "description":"Spot Trading :UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45),Futures Trading: UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45).We apologize for any inconvenience caused. Thank you for your patience and understanding.Should you have any enquiries, please do not hesitate our live chat support or via email at cs@aax.com." + // }, + // "message":"success", + // "ts":1593043237000 + // } + // + const data = this.safeValue (response, 'data', {}); + const timestamp = this.milliseconds (); + const startTime = this.parse8601 (this.safeString (data, 'startTime')); + const endTime = this.parse8601 (this.safeString (data, 'endTime')); + const update = { + 'updated': this.safeInteger (response, 'ts', timestamp), + }; + if (endTime !== undefined) { + const startTimeIsOk = (startTime === undefined) ? true : (timestamp < startTime); + const isOk = (timestamp > endTime) || startTimeIsOk; + update['eta'] = endTime; + update['status'] = isOk ? 'ok' : 'maintenance'; + } + this.status = this.extend (this.status, update); + return this.status; + } + async fetchMarkets (params = {}) { const response = await this.publicGetInstruments (params); // @@ -318,8 +351,8 @@ module.exports = class aax extends Exchange { const quote = this.safeCurrencyCode (quoteId); const status = this.safeString (market, 'status'); const active = (status === 'enable'); - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); const type = this.safeString (market, 'type'); let inverse = undefined; let linear = undefined; @@ -337,8 +370,8 @@ module.exports = class aax extends Exchange { symbol = base + '/' + quote; } const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; result.push ({ 'id': id, @@ -396,8 +429,8 @@ module.exports = class aax extends Exchange { const timestamp = this.safeInteger (ticker, 't'); const marketId = this.safeString (ticker, 's'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'c'); - const open = this.safeFloat (ticker, 'o'); + const last = this.safeNumber (ticker, 'c'); + const open = this.safeNumber (ticker, 'o'); let change = undefined; let percentage = undefined; let average = undefined; @@ -408,13 +441,13 @@ module.exports = class aax extends Exchange { } average = this.sum (last, open) / 2; } - const quoteVolume = this.safeFloat (ticker, 'v'); + const quoteVolume = this.safeNumber (ticker, 'v'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'h'), - 'low': this.safeFloat (ticker, 'l'), + 'high': this.safeNumber (ticker, 'h'), + 'low': this.safeNumber (ticker, 'l'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -561,8 +594,8 @@ module.exports = class aax extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let price = this.safeFloat2 (trade, 'p', 'filledPrice'); - const amount = this.safeFloat2 (trade, 'q', 'filledQty'); + let priceString = this.safeString2 (trade, 'p', 'filledPrice'); + const amountString = this.safeString2 (trade, 'q', 'filledQty'); const orderId = this.safeString (trade, 'orderID'); const isTaker = this.safeValue (trade, 'taker'); let takerOrMaker = undefined; @@ -576,17 +609,15 @@ module.exports = class aax extends Exchange { side = 'sell'; } if (side === undefined) { - side = (price > 0) ? 'buy' : 'sell'; - } - side = (price > 0) ? 'buy' : 'sell'; - price = Math.abs (price); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; + side = (priceString[0] === '-') ? 'sell' : 'buy'; } + priceString = (priceString[0] === '-') ? priceString.slice (1) : priceString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderType = this.parseOrderType (this.safeString (trade, 'orderType')); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -654,11 +685,11 @@ module.exports = class aax extends Exchange { // return [ this.safeTimestamp (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -743,12 +774,12 @@ module.exports = class aax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'unavailable'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'unavailable'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -776,7 +807,7 @@ module.exports = class aax extends Exchange { request['clOrdID'] = clientOrderId; params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { if ((orderType === 'STOP-LIMIT') || (orderType === 'STOP')) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders'); @@ -894,7 +925,7 @@ module.exports = class aax extends Exchange { // 'price': this.priceToPrecision (symbol, price), // 'stopPrice': this.priceToPrecision (symbol, stopPrice), }; - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1531,15 +1562,18 @@ module.exports = class aax extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const price = this.safeFloat (order, 'price'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const price = this.safeNumber (order, 'price'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'Post-Only'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeString (order, 'leavesQty'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + let remaining = this.safeNumber (order, 'leavesQty'); + if ((filled === 0) && (remaining === 0)) { + remaining = undefined; + } let cost = undefined; let lastTradeTimestamp = undefined; if (filled !== undefined) { @@ -1554,7 +1588,7 @@ module.exports = class aax extends Exchange { } } let fee = undefined; - const feeCost = this.safeFloat (order, 'commission'); + const feeCost = this.safeNumber (order, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/acx.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/acx.js deleted file mode 100644 index e10ec85ca..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/acx.js +++ /dev/null @@ -1,487 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { InsufficientFunds, OrderNotFound } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class acx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'acx', - 'name': 'ACX', - 'countries': [ 'AU' ], - 'rateLimit': 1000, - 'version': 'v2', - 'has': { - 'cancelOrder': true, - 'CORS': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchMarkets': true, - 'fetchOHLCV': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTime': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '12h': '720', - '1d': '1440', - '3d': '4320', - '1w': '10080', - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg', - 'extension': '.json', - 'api': 'https://acx.io/api', - 'www': 'https://acx.io', - 'doc': 'https://acx.io/documents/api_v2', - }, - 'api': { - 'public': { - 'get': [ - 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. - 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator - 'k', // Get OHLC(k line) of specific market - 'markets', // Get all available markets - 'order_book', // Get the order book of specified market - 'order_book/{market}', - 'tickers', // Get ticker of all markets - 'tickers/{market}', // Get ticker of specific market - 'timestamp', // Get server current time, in seconds since Unix epoch - 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. - 'trades/{market}', - ], - }, - 'private': { - 'get': [ - 'members/me', // Get your profile and accounts info - 'deposits', // Get your deposits history - 'deposit', // Get details of specific deposit - 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. - 'orders', // Get your orders, results is paginated - 'order', // Get information of specified order - 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. - 'withdraws', // Get your cryptocurrency withdraws - 'withdraw', // Get your cryptocurrency withdraw - ], - 'post': [ - 'orders', // Create a Sell/Buy order - 'orders/multi', // Create multiple sell/buy orders - 'orders/clear', // Cancel all my orders - 'order/delete', // Cancel an order - 'withdraw', // Create a withdraw - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': false, - 'percentage': true, - 'maker': 0.2 / 100, - 'taker': 0.2 / 100, - }, - 'funding': { - 'tierBased': false, - 'percentage': true, - 'withdraw': {}, // There is only 1% fee on withdrawals to your bank account. - }, - }, - 'commonCurrencies': { - 'PLA': 'Plair', - }, - 'exceptions': { - '2002': InsufficientFunds, - '2003': OrderNotFound, - }, - }); - } - - async fetchMarkets (params = {}) { - const markets = await this.publicGetMarkets (params); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = market['id']; - const symbol = market['name']; - let baseId = this.safeString (market, 'base_unit'); - let quoteId = this.safeString (market, 'quote_unit'); - if ((baseId === undefined) || (quoteId === undefined)) { - const ids = symbol.split ('/'); - baseId = ids[0].toLowerCase (); - quoteId = ids[1].toLowerCase (); - } - let base = baseId.toUpperCase (); - let quote = quoteId.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - // todo: find out their undocumented precision and limits - const precision = { - 'amount': 8, - 'price': 8, - }; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'precision': precision, - 'info': market, - 'active': undefined, - 'limits': this.limits, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetMembersMe (params); - const balances = this.safeValue (response, 'accounts'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 300 - } - const orderbook = await this.publicGetDepth (this.extend (request, params)); - const timestamp = this.safeTimestamp (orderbook, 'timestamp'); - return this.parseOrderBook (orderbook, timestamp); - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.safeTimestamp (ticker, 'at'); - ticker = ticker['ticker']; - let symbol = undefined; - if (market) { - symbol = market['symbol']; - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetTickers (params); - const ids = Object.keys (response); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let market = undefined; - let symbol = id; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } else { - let base = id.slice (0, 3); - let quote = id.slice (3, 6); - base = base.toUpperCase (); - quote = quote.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - symbol = base + '/' + quote; - } - result[symbol] = this.parseTicker (response[id], market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTickersMarket (this.extend (request, params)); - return this.parseTicker (response, market); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const id = this.safeString (trade, 'tid'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': undefined, - 'side': undefined, - 'order': undefined, - 'takerOrMaker': undefined, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), - 'cost': this.safeFloat (trade, 'funds'), - 'fee': undefined, - }; - } - - async fetchTime (params = {}) { - const response = await this.publicGetTimestamp (params); - // - // 1594911427 - // - return response * 1000; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - return [ - this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (limit === undefined) { - limit = 500; // default is 30 - } - const request = { - 'market': market['id'], - 'period': this.timeframes[timeframe], - 'limit': limit, - }; - if (since !== undefined) { - request['timestamp'] = parseInt (since / 1000); - } - const response = await this.publicGetK (this.extend (request, params)); - return this.parseOHLCVs (response, market, timeframe, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'done': 'closed', - 'wait': 'open', - 'cancel': 'canceled', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - const marketId = this.safeString (order, 'market'); - const symbol = this.safeSymbol (marketId, market); - const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const status = this.parseOrderStatus (this.safeString (order, 'state')); - const type = this.safeString (order, 'type'); - const side = this.safeString (order, 'side'); - const id = this.safeString (order, 'id'); - return { - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': this.safeFloat (order, 'price'), - 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'volume'), - 'filled': this.safeFloat (order, 'executed_volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'trades': undefined, - 'fee': undefined, - 'info': order, - 'cost': undefined, - 'average': undefined, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': parseInt (id), - }; - const response = await this.privateGetOrder (this.extend (request, params)); - return this.parseOrder (response); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'market': this.marketId (symbol), - 'side': side, - 'volume': amount.toString (), - 'ord_type': type, - }; - if (type === 'limit') { - request['price'] = price.toString (); - } - const response = await this.privatePostOrders (this.extend (request, params)); - const marketId = this.safeValue (response, 'market'); - const market = this.safeValue (this.markets_by_id, marketId); - return this.parseOrder (response, market); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - const response = await this.privatePostOrderDelete (this.extend (request, params)); - const order = this.parseOrder (response); - const status = order['status']; - if (status === 'closed' || status === 'canceled') { - throw new OrderNotFound (this.id + ' ' + this.json (order)); - } - return order; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - // they have XRP but no docs on memo/tag - const request = { - 'currency': currency['id'], - 'sum': amount, - 'address': address, - }; - const response = await this.privatePostWithdraw (this.extend (request, params)); - // withdrawal response is undocumented - return { - 'info': response, - 'id': undefined, - }; - } - - nonce () { - return this.milliseconds (); - } - - encodeParams (params) { - if ('orders' in params) { - const orders = params['orders']; - let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); - for (let i = 0; i < orders.length; i++) { - const order = orders[i]; - const keys = Object.keys (order); - for (let k = 0; k < keys.length; k++) { - const key = keys[k]; - const value = order[key]; - query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); - } - } - return query; - } - return this.urlencode (this.keysort (params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let request = '/api/' + this.version + '/' + this.implodeParams (path, params); - if ('extension' in this.urls) { - request += this.urls['extension']; - } - const query = this.omit (params, this.extractParams (path)); - let url = this.urls['api'] + request; - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce ().toString (); - const query = this.encodeParams (this.extend ({ - 'access_key': this.apiKey, - 'tonce': nonce, - }, params)); - const auth = method + '|' + request + '|' + query; - const signed = this.hmac (this.encode (auth), this.encode (this.secret)); - const suffix = query + '&signature=' + signed; - if (method === 'GET') { - url += '?' + suffix; - } else { - body = suffix; - headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; - } - if (code === 400) { - const error = this.safeValue (response, 'error'); - const errorCode = this.safeString (error, 'code'); - const feedback = this.id + ' ' + this.json (response); - this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); - // fallback to default error handler - } - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aofex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aofex.js index 7899f09d5..69264394e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aofex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/aofex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, BadSymbol, InvalidOrder, PermissionDenied, InvalidAddress, AuthenticationError, InvalidNonce, BadRequest, InsufficientFunds, OrderNotFound } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -193,8 +194,8 @@ module.exports = class aofex extends Exchange { const symbol = base + '/' + quote; const numericId = this.safeInteger (market, 'id'); const precision = this.safeValue (precisions, id, {}); - const makerFee = this.safeFloat (market, 'maker_fee'); - const takerFee = this.safeFloat (market, 'taker_fee'); + const makerFee = this.safeNumber (market, 'maker_fee'); + const takerFee = this.safeNumber (market, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -212,12 +213,12 @@ module.exports = class aofex extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -245,11 +246,11 @@ module.exports = class aofex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -328,11 +329,11 @@ module.exports = class aofex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -355,8 +356,8 @@ module.exports = class aofex extends Exchange { return { 'info': response, 'symbol': symbol, - 'maker': this.safeFloat (result, 'fromFee'), - 'taker': this.safeFloat (result, 'toFee'), + 'maker': this.safeNumber (result, 'fromFee'), + 'taker': this.safeNumber (result, 'toFee'), }; } @@ -413,8 +414,8 @@ module.exports = class aofex extends Exchange { if (market) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); let change = undefined; if (symbol !== undefined) { change = parseFloat (this.priceToPrecision (symbol, last - open)); @@ -423,8 +424,8 @@ module.exports = class aofex extends Exchange { } const average = this.sum (last, open) / 2; const percentage = change / open * 100; - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); let vwap = this.vwap (baseVolume, quoteVolume); if (vwap !== undefined) { vwap = parseFloat (this.priceToPrecision (symbol, vwap)); @@ -433,8 +434,8 @@ module.exports = class aofex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -552,13 +553,15 @@ module.exports = class aofex extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'number'); - let cost = this.safeFloat (trade, 'total_price'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'number'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total_price'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -702,21 +705,21 @@ module.exports = class aofex extends Exchange { const orderType = this.safeString (order, 'type'); const type = (orderType === '2') ? 'limit' : 'market'; const side = this.safeString (order, 'side'); - // const amount = this.safeFloat (order, 'number'); - // const price = this.safeFloat (order, 'price'); + // const amount = this.safeNumber (order, 'number'); + // const price = this.safeNumber (order, 'price'); let cost = undefined; let price = undefined; let amount = undefined; let average = undefined; - const number = this.safeFloat (order, 'number'); - const totalPrice = this.safeFloat (order, 'total_price'); + const number = this.safeNumber (order, 'number'); + const totalPrice = this.safeNumber (order, 'total_price'); if (type === 'limit') { amount = number; - price = this.safeFloat (order, 'price'); + price = this.safeNumber (order, 'price'); } else { - average = this.safeFloat (order, 'deal_price'); + average = this.safeNumber (order, 'deal_price'); if (side === 'buy') { - amount = this.safeFloat (order, 'deal_number'); + amount = this.safeNumber (order, 'deal_number'); } else { amount = number; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ascendex.js similarity index 93% rename from Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmax.js rename to Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ascendex.js index 62cbf55d5..753148db2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ascendex.js @@ -4,16 +4,17 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class bitmax extends Exchange { +module.exports = class ascendex extends Exchange { describe () { return this.deepExtend (super.describe (), { - 'id': 'bitmax', - 'name': 'BitMax', - 'countries': [ 'CN' ], // China + 'id': 'ascendex', + 'name': 'AscendEX', + 'countries': [ 'SG', 'CN' ], // Singapore, China 'rateLimit': 500, // new metainfo interface 'has': { @@ -55,14 +56,14 @@ module.exports = class bitmax extends Exchange { }, 'version': 'v1', 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg', - 'api': 'https://bitmax.io', + 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg', + 'api': 'https://ascendex.com', 'test': 'https://bitmax-test.io', - 'www': 'https://bitmax.io', + 'www': 'https://ascendex.com', 'doc': [ 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', ], - 'fees': 'https://bitmax.io/#/feeRate/tradeRate', + 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate', 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', }, 'api': { @@ -131,6 +132,7 @@ module.exports = class bitmax extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'taker': 0.002, @@ -212,6 +214,7 @@ module.exports = class bitmax extends Exchange { 'broad': {}, }, 'commonCurrencies': { + 'BOND': 'BONDED', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', }, @@ -294,7 +297,7 @@ module.exports = class bitmax extends Exchange { const code = this.safeCurrencyCode (id); const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); // why would the exchange API have different names for the same field - const fee = this.safeFloat2 (currency, 'withdrawFee', 'withdrawalFee'); + const fee = this.safeNumber2 (currency, 'withdrawFee', 'withdrawalFee'); const status = this.safeString2 (currency, 'status', 'statusCode'); const active = (status === 'Normal'); const margin = ('borrowAssetCode' in currency); @@ -322,7 +325,7 @@ module.exports = class bitmax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawalAmt'), + 'min': this.safeNumber (currency, 'minWithdrawalAmt'), 'max': undefined, }, }, @@ -423,8 +426,8 @@ module.exports = class bitmax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'Normal'); @@ -450,16 +453,16 @@ module.exports = class bitmax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minQty'), - 'max': this.safeFloat (market, 'maxQty'), + 'min': this.safeNumber (market, 'minQty'), + 'max': this.safeNumber (market, 'maxQty'), }, 'price': { - 'min': this.safeFloat (market, 'tickSize'), + 'min': this.safeNumber (market, 'tickSize'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minNotional'), - 'max': this.safeFloat (market, 'maxNotional'), + 'min': this.safeNumber (market, 'minNotional'), + 'max': this.safeNumber (market, 'maxNotional'), }, }, }); @@ -467,28 +470,6 @@ module.exports = class bitmax extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - // TODO: fee calculation here is incorrect, we need to support tiered fee calculation. - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { let accountGroup = this.safeString (this.options, 'account-group'); let response = undefined; @@ -593,11 +574,11 @@ module.exports = class bitmax extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -669,10 +650,10 @@ module.exports = class bitmax extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', []); const ask = this.safeValue (ticker, 'ask', []); - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; let average = undefined; @@ -687,12 +668,12 @@ module.exports = class bitmax extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 0), - 'bidVolume': this.safeFloat (bid, 1), - 'ask': this.safeFloat (ask, 0), - 'askVolume': this.safeFloat (ask, 1), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 0), + 'bidVolume': this.safeNumber (bid, 1), + 'ask': this.safeNumber (ask, 0), + 'askVolume': this.safeNumber (ask, 1), 'vwap': undefined, 'open': open, 'close': close, @@ -701,20 +682,12 @@ module.exports = class bitmax extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -791,11 +764,11 @@ module.exports = class bitmax extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.safeInteger (data, 'ts'), - this.safeFloat (data, 'o'), - this.safeFloat (data, 'h'), - this.safeFloat (data, 'l'), - this.safeFloat (data, 'c'), - this.safeFloat (data, 'v'), + this.safeNumber (data, 'o'), + this.safeNumber (data, 'h'), + this.safeNumber (data, 'l'), + this.safeNumber (data, 'c'), + this.safeNumber (data, 'v'), ]; } @@ -860,12 +833,11 @@ module.exports = class bitmax extends Exchange { // } // const timestamp = this.safeInteger (trade, 'ts'); - const price = this.safeFloat2 (trade, 'price', 'p'); - const amount = this.safeFloat (trade, 'q'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString2 (trade, 'price', 'p'); + const amountString = this.safeString (trade, 'q'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const buyerIsMaker = this.safeValue (trade, 'bm', false); const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; const side = buyerIsMaker ? 'buy' : 'sell'; @@ -989,26 +961,12 @@ module.exports = class bitmax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '/'); - let timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); - let lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const average = this.safeFloat (order, 'avgPx'); - const filled = this.safeFloat2 (order, 'cumFilledQty', 'cumQty'); - let remaining = undefined; - if (filled !== undefined) { - if (filled === 0) { - timestamp = lastTradeTimestamp; - lastTradeTimestamp = undefined; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - let cost = undefined; - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } + const timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); + const lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const average = this.safeNumber (order, 'avgPx'); + const filled = this.safeNumber2 (order, 'cumFilledQty', 'cumQty'); const id = this.safeString (order, 'orderId'); let clientOrderId = this.safeString (order, 'id'); if (clientOrderId !== undefined) { @@ -1018,7 +976,7 @@ module.exports = class bitmax extends Exchange { } const type = this.safeStringLower (order, 'orderType'); const side = this.safeStringLower (order, 'side'); - const feeCost = this.safeFloat (order, 'cumFee'); + const feeCost = this.safeNumber (order, 'cumFee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeAsset'); @@ -1028,8 +986,8 @@ module.exports = class bitmax extends Exchange { 'currency': feeCurrencyCode, }; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1044,14 +1002,14 @@ module.exports = class bitmax extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1088,7 +1046,7 @@ module.exports = class bitmax extends Exchange { request['orderPrice'] = this.priceToPrecision (symbol, price); } if ((type === 'stop_limit') || (type === 'stop_market')) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); } else { @@ -1624,7 +1582,7 @@ module.exports = class bitmax extends Exchange { // } // const id = this.safeString (transaction, 'requestId'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const destAddress = this.safeValue (transaction, 'destAddress', {}); const address = this.safeString (destAddress, 'address'); const tag = this.safeString (destAddress, 'destTag'); @@ -1634,7 +1592,7 @@ module.exports = class bitmax extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'commission'); + const feeCost = this.safeNumber (transaction, 'commission'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Exchange.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Exchange.js index eb017b5bf..0cf2c9fb0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Exchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Exchange.js @@ -44,6 +44,7 @@ const { // eslint-disable-line object-curly-newline const { TRUNCATE, ROUND, DECIMAL_PLACES, NO_PADDING } = functions.precisionConstants const BN = require ('../static_dependencies/BN/bn') +const Precise = require ('./Precise') // ---------------------------------------------------------------------------- @@ -224,6 +225,11 @@ module.exports = class Exchange { this.minFundingAddressLength = 1 // used in checkAddress this.substituteCommonCurrencyCodes = true // reserved + this.quoteJsonNumbers = true // treat numbers in json as quoted precise strings + this.number = Number // or String (a pointer to a function) + + // whether fees should be summed by currency code + this.reduceFees = true // do not delete this line, it is needed for users to be able to define their own fetchImplementation this.fetchImplementation = defaultFetch @@ -519,7 +525,7 @@ module.exports = class Exchange { parseJson (jsonString) { try { if (this.isJsonEncodedObject (jsonString)) { - return JSON.parse (jsonString) + return JSON.parse (this.onJsonResponse (jsonString)) } } catch (e) { // SyntaxError @@ -598,7 +604,11 @@ module.exports = class Exchange { } onRestResponse (statusCode, statusText, url, method, responseHeaders, responseBody, requestHeaders, requestBody) { - return responseBody.trim ().replace (/:(\d{15,}),/g, ':"$1",'); + return responseBody.trim () + } + + onJsonResponse (responseBody) { + return this.quoteJsonNumbers ? responseBody.replace (/":([+.0-9eE-]+),/g, '":"$1",') : responseBody; } setMarkets (markets, currencies = undefined) { @@ -918,8 +928,8 @@ module.exports = class Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = parseFloat (bidask[priceKey]) - const amount = parseFloat (bidask[amountKey]) + const price = this.safeNumber (bidask, priceKey) + const amount = this.safeNumber (bidask, amountKey) return [ price, amount ] } @@ -945,7 +955,7 @@ module.exports = class Exchange { } } - parseBalance (balance) { + parseBalance (balance, legacy = true) { const codes = Object.keys (this.omit (balance, [ 'info', 'free', 'used', 'total' ])); @@ -957,20 +967,34 @@ module.exports = class Exchange { const code = codes[i] if (balance[code].total === undefined) { if (balance[code].free !== undefined && balance[code].used !== undefined) { - balance[code].total = this.sum (balance[code].free, balance[code].used) + if (legacy) { + balance[code].total = this.sum (balance[code].free, balance[code].used) + } else { + balance[code].total = Precise.stringAdd (balance[code].free, balance[code].used) + } } } if (balance[code].free === undefined) { if (balance[code].total !== undefined && balance[code].used !== undefined) { - balance[code].free = this.sum (balance[code].total, -balance[code].used) + if (legacy) { + balance[code].free = this.sum (balance[code].total, -balance[code].used) + } else { + balance[code].free = Precise.stringSub (balance[code].total, balance[code].used) + } } } if (balance[code].used === undefined) { if (balance[code].total !== undefined && balance[code].free !== undefined) { - balance[code].used = this.sum (balance[code].total, -balance[code].free) + if (legacy) { + balance[code].used = this.sum (balance[code].total, -balance[code].free) + } else { + balance[code].used = Precise.stringSub (balance[code].total, balance[code].free) + } } } - + balance[code].free = this.parseNumber (balance[code].free) + balance[code].used = this.parseNumber (balance[code].used) + balance[code].total = this.parseNumber (balance[code].total) balance.free[code] = balance[code].free balance.used[code] = balance[code].used balance.total[code] = balance[code].total @@ -979,6 +1003,10 @@ module.exports = class Exchange { return balance } + async fetchBalance (params = {}) { + throw new NotSupported (this.id + ' fetchBalance not supported yet') + } + async fetchPartialBalance (part, params = {}) { const balance = await this.fetchBalance (params) return balance[part] @@ -1088,11 +1116,27 @@ module.exports = class Exchange { return indexed ? indexBy (result, key) : result } + parseTickers (tickers, symbols = undefined) { + const result = []; + for (let i = 0; i < tickers.length; i++) { + result.push (this.parseTicker (tickers[i])); + } + return this.filterByArray (result, 'symbol', symbols); + } + + parseDepositAddresses (addresses, codes = undefined) { + let result = []; + for (let i = 0; i < addresses.length; i++) { + const address = this.parseDepositAddress (addresses[i]); + result.push (address); + } + if (codes) { + result = this.filterByArray (result, 'currency', codes); + } + return this.indexBy (result, 'currency'); + } + parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (trades)) { - // throw new ExchangeError (this.id + ' parseTrades expected an array in the trades argument, but got ' + typeof trades); - // } let result = Object.values (trades || []).map ((trade) => this.extend (this.parseTrade (trade, market), params)) result = sortBy (result, 'timestamp') const symbol = (market !== undefined) ? market['symbol'] : undefined @@ -1101,10 +1145,6 @@ module.exports = class Exchange { } parseTransactions (transactions, currency = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (transactions)) { - // throw new ExchangeError (this.id + ' parseTransactions expected an array in the transactions argument, but got ' + typeof transactions); - // } let result = Object.values (transactions || []).map ((transaction) => this.extend (this.parseTransaction (transaction, currency), params)) result = this.sortBy (result, 'timestamp'); const code = (currency !== undefined) ? currency['code'] : undefined; @@ -1112,6 +1152,14 @@ module.exports = class Exchange { return this.filterByCurrencySinceLimit (result, code, since, limit, tail); } + parseTransfers (transfers, currency = undefined, since = undefined, limit = undefined, params = {}) { + let result = Object.values (transfers || []).map ((transfer) => this.extend (this.parseTransfer (transfer, currency), params)) + result = this.sortBy (result, 'timestamp'); + const code = (currency !== undefined) ? currency['code'] : undefined; + const tail = since === undefined; + return this.filterByCurrencySinceLimit (result, code, since, limit, tail); + } + parseLedger (data, currency = undefined, since = undefined, limit = undefined, params = {}) { let result = []; const array = Object.values (data || []); @@ -1256,19 +1304,19 @@ module.exports = class Exchange { return this.createOrder (symbol, ...args) } - createLimitOrder (symbol, side, amount, price = undefined, params = {}) { + createLimitOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'limit', side, amount, price, params) } - createMarketOrder (symbol, side, amount, price = undefined, params = {}) { + createMarketOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'market', side, amount, price, params) } - createLimitBuyOrder (symbol, amount, price = undefined, params = {}) { + createLimitBuyOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'buy', amount, price, params) } - createLimitSellOrder (symbol, amount, price = undefined, params = {}) { + createLimitSellOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'sell', amount, price, params) } @@ -1301,15 +1349,43 @@ module.exports = class Exchange { } calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol] - const rate = market[takerOrMaker] - const cost = parseFloat (this.costToPrecision (symbol, amount * price)) + const market = this.markets[symbol]; + const feeSide = this.safeString (market, 'feeSide', 'quote'); + let key = 'quote'; + let cost = undefined; + if (feeSide === 'quote') { + // the fee is always in quote currency + cost = amount * price; + } else if (feeSide === 'base') { + // the fee is always in base currency + cost = amount; + } else if (feeSide === 'get') { + // the fee is always in the currency you get + cost = amount; + if (side === 'sell') { + cost *= price; + } else { + key = 'base'; + } + } else if (feeSide === 'give') { + // the fee is always in the currency you give + cost = amount; + if (side === 'buy') { + cost *= price; + } else { + key = 'base'; + } + } + const rate = market[takerOrMaker]; + if (cost !== undefined) { + cost *= rate; + } return { 'type': takerOrMaker, - 'currency': market['quote'], + 'currency': market[key], 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, rate * cost)), - } + 'cost': cost, + }; } checkRequiredDependencies () { @@ -1393,6 +1469,25 @@ module.exports = class Exchange { return new BN (a).pow (new BN (b)) } + reduceFeesByCurrency (fees) { + const reduced = {}; + for (let i = 0; i < fees.length; i++) { + const fee = fees[i]; + const feeCurrencyCode = this.safeValue (fee, 'currency'); + if (feeCurrencyCode !== undefined) { + if (feeCurrencyCode in reduced) { + reduced[feeCurrencyCode]['cost'] = this.sum (reduced[feeCurrencyCode]['cost'], fee['cost']); + } else { + reduced[feeCurrencyCode] = { + 'cost': fee['cost'], + 'currency': feeCurrencyCode, + }; + } + } + } + return Object.values (reduced); + } + safeOrder (order) { // Cost // Remaining @@ -1401,65 +1496,143 @@ module.exports = class Exchange { // Amount // Filled // - // First we try to calculate filled from the trades - const parseFilled = order['filled'] === undefined; - const parseCost = order['cost'] === undefined; - if (parseFilled) { - order['filled'] = 0 - } - if (parseCost) { - order['cost'] = 0 - } - if (parseFilled || parseCost) { - if (Array.isArray (order['trades'])) { - for (let i = 0; i < order['trades'].length; i++) { - const trade = order['trades'][i] - if (parseFilled) { - order['filled'] = this.sum (order['filled'], trade['amount']) + // first we try to calculate the order fields from the trades + let amount = this.safeValue (order, 'amount'); + let remaining = this.safeValue (order, 'remaining'); + let filled = this.safeValue (order, 'filled'); + let cost = this.safeValue (order, 'cost'); + let average = this.safeValue (order, 'average'); + let price = this.safeValue (order, 'price'); + let lastTradeTimeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); + const parseFilled = (filled === undefined); + const parseCost = (cost === undefined); + const parseLastTradeTimeTimestamp = (lastTradeTimeTimestamp === undefined); + const parseFee = this.safeValue (order, 'fee') === undefined; + const parseFees = this.safeValue (order, 'fees') === undefined; + const shouldParseFees = parseFee || parseFees; + const fees = shouldParseFees ? [] : undefined; + if (parseFilled || parseCost || shouldParseFees) { + const trades = this.safeValue (order, 'trades'); + if (trades !== undefined) { + if (parseFilled) { + filled = 0; + } + if (parseCost) { + cost = 0; + } + for (let i = 0; i < trades.length; i++) { + const trade = trades[i]; + const tradeAmount = this.safeValue (trade, 'amount'); + if (parseFilled && (tradeAmount !== undefined)) { + filled = this.sum (filled, tradeAmount); } - if (parseCost) { - order['cost'] = this.sum (order['cost'], trade['cost']) + const tradeCost = this.safeValue (trade, 'cost'); + if (parseCost && (tradeCost !== undefined)) { + cost = this.sum (cost, tradeCost); + } + const tradeTimestamp = this.safeValue (trade, 'timestamp'); + if (parseLastTradeTimeTimestamp && (tradeTimestamp !== undefined)) { + if (lastTradeTimeTimestamp === undefined) { + lastTradeTimeTimestamp = tradeTimestamp; + } else { + lastTradeTimeTimestamp = Math.max (lastTradeTimeTimestamp, tradeTimestamp); + } + } + if (shouldParseFees) { + const tradeFees = this.safeValue (trade, 'fees'); + if (tradeFees !== undefined) { + for (let j = 0; j < tradeFees.length; j++) { + const tradeFee = tradeFees[j]; + fees.push (this.extend ({}, tradeFee)); + } + } else { + const tradeFee = this.safeValue (trade, 'fee'); + if (tradeFee !== undefined) { + fees.push (this.extend ({}, tradeFee)); + } + } } } } } - // We ensure amount = filled + remaining - if (order['amount'] === undefined) { - if (order['filled'] !== undefined && order['remaining'] !== undefined) { - order['amount'] = this.sum (order['filled'], order['remaining']) + if (shouldParseFees) { + const reducedFees = this.reduceFees ? this.reduceFeesByCurrency (fees) : fees; + const reducedLength = reducedFees.length; + if (!parseFee && (reducedLength === 0)) { + reducedFees.push (order['fee']); + } + if (parseFees) { + order['fees'] = reducedFees; + } + if (parseFee && (reducedLength === 1)) { + order['fee'] = reducedFees[0]; } } - if (order['filled'] === undefined) { - if (order['amount'] !== undefined && order['remaining'] !== undefined) { - order['filled'] = Math.max (this.sum (order['amount'], -order['remaining']), 0) + if (amount === undefined) { + // ensure amount = filled + remaining + if (filled !== undefined && remaining !== undefined) { + amount = this.sum (filled, remaining); + } else if (this.safeString (order, 'status') === 'closed') { + amount = filled; } } - if (order['remaining'] === undefined) { - if (order['amount'] !== undefined && order['filled'] !== undefined) { - order['remaining'] = Math.max (this.sum (order['amount'], -order['filled']), 0) + if (filled === undefined) { + if (amount !== undefined && remaining !== undefined) { + filled = Math.max (this.sum (amount, -remaining), 0); } } - // We ensure that the average field is calculated correctly - if (order['average'] === undefined) { - if (order['filled'] !== undefined && order['cost'] !== undefined && order['cost'] > 0) { - order['average'] = order['filled'] / order['cost'] + if (remaining === undefined) { + if (amount !== undefined && filled !== undefined) { + remaining = Math.max (this.sum (amount, -filled), 0); } } - // We also ensure the cost field is calculated correctly - const costPriceExists = (order['average'] !== undefined) || (order['price'] !== undefined) - if ((order['filled'] !== undefined) && costPriceExists) { - let costPrice = undefined; - if (order['average'] === undefined) { - costPrice = order['price'] - } else { - costPrice = order['average'] + // ensure that the average field is calculated correctly + if (average === undefined) { + if ((filled !== undefined) && (cost !== undefined) && (cost > 0)) { + average = cost / filled; } - order['cost'] = costPrice * order['filled'] } - // We add support for market orders - if (order['price'] === undefined && order['type'] === 'market') { - order['price'] = order['average'] + // also ensure the cost field is calculated correctly + const costPriceExists = (average !== undefined) || (price !== undefined); + if (parseCost && (filled !== undefined) && costPriceExists) { + cost = (average === undefined) ? (price * filled) : (average * filled); } - return order + // support for market orders + const orderType = this.safeValue (order, 'type'); + const emptyPrice = (price === undefined) || (price === 0.0); + if (emptyPrice && (orderType === 'market')) { + price = average; + } + return this.extend (order, { + 'lastTradeTimestamp': lastTradeTimeTimestamp, + 'price': price, + 'amount': amount, + 'cost': cost, + 'average': average, + 'filled': filled, + 'remaining': remaining, + }); + } + + parseNumber (value, d = undefined) { + if (value === undefined) { + return d + } else { + try { + return this.number (value) + } catch (e) { + return d + } + } + } + + safeNumber (object, key, d = undefined) { + const value = this.safeString (object, key) + return this.parseNumber (value, d) + } + + safeNumber2 (object, key1, key2, d = undefined) { + const value = this.safeString2 (object, key1, key2) + return this.parseNumber (value, d) } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Precise.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Precise.js new file mode 100644 index 000000000..9bf17ad8d --- /dev/null +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/Precise.js @@ -0,0 +1,145 @@ +'use strict' + +const BN = require ('../static_dependencies/BN/bn') + +class Precise { + constructor (number, decimals = 0) { + const isBN = number instanceof BN + const isString = typeof number === 'string' + if (!(isBN || isString)) { + throw new Error ('Precise initiated with something other than a string or BN') + } + if (isBN) { + this.integer = number + this.decimals = decimals + } else { + if (decimals) { + throw new Error ('Cannot set decimals when initializing with a string') + } + let modifier = 0 + number = number.toLowerCase () + if (number.indexOf ('e') > -1) { + [ number, modifier ] = number.split ('e') + modifier = parseInt (modifier) + } + const decimalIndex = number.indexOf ('.') + this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0 + const integerString = number.replace ('.', '') + this.integer = new BN (integerString) + this.decimals = this.decimals - modifier + } + this.base = 10 + this.reduce () + } + + mul (other) { + // other must be another instance of Precise + const integerResult = this.integer.mul (other.integer) + return new Precise (integerResult, this.decimals + other.decimals) + } + + div (other, precision = 18) { + const distance = precision - this.decimals + other.decimals + let numerator + if (distance === 0) { + numerator = this.integer + } else if (distance < 0) { + const exponent = new BN (this.base).pow (new BN (-distance)) + numerator = this.integer.div (exponent) + } else { + const exponent = new BN (this.base).pow (new BN (distance)) + numerator = this.integer.mul (exponent) + } + const result = numerator.div (other.integer) + return new Precise (result, precision) + } + + add (other) { + if (this.decimals === other.decimals) { + const integerResult = this.integer.add (other.integer) + return new Precise (integerResult, this.decimals) + } else { + const [ smaller, bigger ] = + (this.decimals > other.decimals) ? [ other, this ] : [ this, other ] + const exponent = new BN (bigger.decimals - smaller.decimals) + const normalised = smaller.integer.mul (new BN (this.base).pow (exponent)) + const result = normalised.add (bigger.integer) + return new Precise (result, bigger.decimals) + } + } + + sub (other) { + const negative = new Precise (other.integer.neg (), other.decimals) + return this.add (negative) + } + + reduce () { + const zero = new BN (0) + if (this.integer.eq (zero)) { + this.decimals = 0 + return this + } + const base = new BN (this.base) + let divmod = this.integer.divmod (base) + while (divmod.mod.eq (zero)) { + this.integer = divmod.div + this.decimals-- + divmod = this.integer.divmod (base) + } + return this + } + + toString () { + const sign = this.integer.negative ? '-' : '' + const integerArray = Array.from (this.integer.abs ().toString (this.base).padStart (this.decimals, '0')) + const index = integerArray.length - this.decimals + let item + if (index === 0) { + // if we are adding to the front + item = '0.' + } else if (this.decimals < 0) { + item = '0'.repeat (-this.decimals) + } else if (this.decimals === 0) { + item = '' + } else { + item = '.' + } + integerArray.splice (index, 0, item) + return sign + integerArray.join ('') + } + + static stringMul (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).mul (new Precise (string2)).toString () + } + + static stringDiv (string1, string2, precision = 18) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).div (new Precise (string2), precision).toString () + } + + static stringAdd (string1, string2) { + if ((string1 === undefined) && (string2 === undefined)) { + return undefined + } + if (string1 === undefined) { + return string2 + } else if (string2 === undefined) { + return string1 + } + return (new Precise (string1)).add (new Precise (string2)).toString () + } + + static stringSub (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).sub (new Precise (string2)).toString () + } +} + +module.exports = Precise; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/functions/encode.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/functions/encode.js index 0b4331ccf..e64251dbc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/functions/encode.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/base/functions/encode.js @@ -19,7 +19,6 @@ let base58Encoder = null module.exports = { json: (data, params = undefined) => JSON.stringify (data) - , unjson: JSON.parse , isJsonEncodedObject: object => ( (typeof object === 'string') && diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bibox.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bibox.js index 4d46d8f35..ed9826a1a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bibox.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bibox.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AccountSuspended, ArgumentsRequired, AuthenticationError, DDoSProtection, ExchangeNotAvailable, InvalidOrder, OrderNotFound, PermissionDenied, InsufficientFunds, BadSymbol, RateLimitExceeded, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -229,9 +230,9 @@ module.exports = class bibox extends Exchange { const quote = this.safeCurrencyCode (quoteId); symbol = base + '/' + quote; } - const last = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); - const baseVolume = this.safeFloat2 (ticker, 'vol', 'vol24H'); + const last = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); + const baseVolume = this.safeNumber2 (ticker, 'vol', 'vol24H'); let open = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; @@ -245,11 +246,11 @@ module.exports = class bibox extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -260,7 +261,7 @@ module.exports = class bibox extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': baseVolume, - 'quoteVolume': this.safeFloat (ticker, 'amount'), + 'quoteVolume': this.safeNumber (ticker, 'amount'), 'info': ticker, }; } @@ -276,17 +277,6 @@ module.exports = class bibox extends Exchange { return this.parseTicker (response['result'], market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - const ticker = this.parseTicker (rawTickers[i]); - if ((symbols === undefined) || (this.inArray (ticker['symbol'], symbols))) { - tickers.push (ticker); - } - } - return tickers; - } - async fetchTickers (symbols = undefined, params = {}) { const request = { 'cmd': 'marketAll', @@ -319,7 +309,7 @@ module.exports = class bibox extends Exchange { symbol = market['symbol']; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = this.safeString (trade, 'fee_symbol'); if (feeCurrency !== undefined) { if (feeCurrency in this.currencies_by_id) { @@ -329,12 +319,11 @@ module.exports = class bibox extends Exchange { } } const feeRate = undefined; // todo: deduce from market if market is defined - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if (feeCost !== undefined) { fee = { 'cost': -feeCost, @@ -385,7 +374,7 @@ module.exports = class bibox extends Exchange { request['size'] = limit; // default = 200 } const response = await this.publicGetMdata (this.extend (request, params)); - return this.parseOrderBook (response['result'], this.safeFloat (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); + return this.parseOrderBook (response['result'], this.safeNumber (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); } parseOHLCV (ohlcv, market = undefined) { @@ -401,11 +390,11 @@ module.exports = class bibox extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -497,7 +486,7 @@ module.exports = class bibox extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw_min'), + 'min': this.safeNumber (currency, 'withdraw_min'), 'max': undefined, }, }, @@ -629,19 +618,17 @@ module.exports = class bibox extends Exchange { code = this.currencies_by_id[code]['code']; } const account = this.account (); - let balance = indexed[id]; + const balance = indexed[id]; if (typeof balance === 'string') { - balance = parseFloat (balance); account['free'] = balance; - account['used'] = 0.0; account['total'] = balance; } else { - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -732,8 +719,8 @@ module.exports = class bibox extends Exchange { let tag = this.safeString (transaction, 'addr_remark'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'fee'); if (type === 'deposit') { feeCost = 0; tag = undefined; @@ -841,26 +828,19 @@ module.exports = class bibox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const type = (order['order_type'] === 1) ? 'market' : 'limit'; - const timestamp = order['createdAt']; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'deal_price'); - const filled = this.safeFloat (order, 'deal_amount'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat2 (order, 'deal_money', 'money'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - cost = price * filled; - } - } - const side = (order['order_side'] === 1) ? 'buy' : 'sell'; + const rawType = this.safeString (order, 'order_type'); + const type = (rawType === '1') ? 'market' : 'limit'; + const timestamp = this.safeInteger (order, 'createdAt'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'deal_price'); + const filled = this.safeNumber (order, 'deal_amount'); + const amount = this.safeNumber (order, 'amount'); + const cost = this.safeNumber2 (order, 'deal_money', 'money'); + const rawSide = this.safeString (order, 'order_side'); + const side = (rawSide === '1') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -868,8 +848,7 @@ module.exports = class bibox extends Exchange { 'currency': undefined, }; } - cost = cost ? cost : (parseFloat (price) * filled); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -887,11 +866,11 @@ module.exports = class bibox extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -1059,7 +1038,7 @@ module.exports = class bibox extends Exchange { }; const response = await this.privatePostTransfer (request); info[code] = response; - withdrawFees[code] = this.safeFloat (response['result'], 'withdraw_fee'); + withdrawFees[code] = this.safeNumber (response['result'], 'withdraw_fee'); } return { 'info': info, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bigone.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bigone.js index d6e940c4d..f30eec7a4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bigone.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bigone.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, OrderNotFound, InsufficientFunds, PermissionDenied, BadRequest, RateLimitExceeded, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -260,28 +261,28 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (ticker, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = undefined; - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', {}); const ask = this.safeValue (ticker, 'ask', {}); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 'price'), - 'bidVolume': this.safeFloat (bid, 'quantity'), - 'ask': this.safeFloat (ask, 'price'), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 'price'), + 'bidVolume': this.safeNumber (bid, 'quantity'), + 'ask': this.safeNumber (ask, 'price'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, 'last': close, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'daily_change'), + 'change': this.safeNumber (ticker, 'daily_change'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -446,16 +447,13 @@ module.exports = class bigone extends Exchange { // } // const timestamp = this.parse8601 (this.safeString2 (trade, 'created_at', 'inserted_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } let side = this.safeString (trade, 'side'); const takerSide = this.safeString (trade, 'taker_side'); let takerOrMaker = undefined; @@ -529,8 +527,8 @@ module.exports = class bigone extends Exchange { takerCurrencyCode = market['quote']; } } - const makerFeeCost = this.safeFloat (trade, 'maker_fee'); - const takerFeeCost = this.safeFloat (trade, 'taker_fee'); + const makerFeeCost = this.safeNumber (trade, 'maker_fee'); + const takerFeeCost = this.safeNumber (trade, 'taker_fee'); if (makerFeeCost !== undefined) { if (takerFeeCost !== undefined) { result['fees'] = [ @@ -593,11 +591,11 @@ module.exports = class bigone extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -668,11 +666,11 @@ module.exports = class bigone extends Exchange { const symbol = this.safeString (balance, 'asset_symbol'); const code = this.safeCurrencyCode (symbol); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -694,13 +692,9 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (order, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (amount !== undefined && filled !== undefined) { - remaining = Math.max (0, amount - filled); - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); const status = this.parseOrderStatus (this.safeString (order, 'state')); let side = this.safeString (order, 'side'); if (side === 'BID') { @@ -708,15 +702,9 @@ module.exports = class bigone extends Exchange { } else { side = 'sell'; } - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'updated_at')); - const average = this.safeFloat (order, 'avg_deal_price'); - return { + const average = this.safeNumber (order, 'avg_deal_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -731,14 +719,14 @@ module.exports = class bigone extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -762,7 +750,7 @@ module.exports = class bigone extends Exchange { const isStopLimit = (uppercaseType === 'STOP_LIMIT'); const isStopMarket = (uppercaseType === 'STOP_MARKET'); if (isStopLimit || isStopMarket) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price parameter'); } @@ -1101,7 +1089,7 @@ module.exports = class bigone extends Exchange { const currencyId = this.safeString (transaction, 'asset_symbol'); const code = this.safeCurrencyCode (currencyId); const id = this.safeInteger (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const timestamp = this.parse8601 (this.safeString (transaction, 'inserted_at')); const updated = this.parse8601 (this.safeString2 (transaction, 'updated_at', 'completed_at')); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/binance.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/binance.js index a115b3f7b..a5865c442 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/binance.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/binance.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, RateLimitExceeded, PermissionDenied, NotSupported, BadRequest, BadSymbol, AccountSuspended, OrderImmediatelyFillable } = require ('./base/errors'); -const { ROUND, TRUNCATE } = require ('./base/functions/number'); +const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -47,6 +48,8 @@ module.exports = class binance extends Exchange { 'fetchTransactions': false, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, + 'fetchTransfers': true, }, 'timeframes': { '1m': '1m', @@ -195,6 +198,26 @@ module.exports = class binance extends Exchange { 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/recentRecord', 'apiReferral/kickback/historicalRecord', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccount', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/info', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/recentRecord', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/status', + 'broker/subAccount/depositHist', + 'broker/subAccount/spotSummary', + 'broker/subAccount/marginSummary', + 'broker/subAccount/futuresSummary', + 'broker/rebate/futures/recentRecord', + 'broker/subAccountApi/ipRestriction', + 'broker/universalTransfer', + // v2 not supported yet + // GET /sapi/v2/broker/subAccount/futuresSummary ], 'post': [ 'asset/dust', @@ -234,11 +257,30 @@ module.exports = class binance extends Exchange { // leveraged token endpoints 'blvt/subscribe', 'blvt/redeem', - // broker api + // brokerage API 'apiReferral/customization', 'apiReferral/userCustomization', 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/historicalRecord', + 'broker/subAccount', + 'broker/subAccount/margin', + 'broker/subAccount/futures', + 'broker/subAccountApi', + 'broker/subAccountApi/permission', + 'broker/subAccountApi/commission', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/spot', + 'broker/subAccount/bnbBurn/marginInterest', + 'broker/subAccount/blvt', + 'broker/subAccountApi/ipRestriction', + 'broker/subAccountApi/ipRestriction/ipList', + 'broker/universalTransfer', + 'broker/subAccountApi/permission/universalTransfer', + 'broker/subAccountApi/permission/vanillaOptions', ], 'put': [ 'userDataStream', @@ -249,6 +291,9 @@ module.exports = class binance extends Exchange { 'margin/order', 'userDataStream', 'userDataStream/isolated', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccountApi/ipRestriction/ipList', ], }, 'wapi': { @@ -385,6 +430,8 @@ module.exports = class binance extends Exchange { 'positionSide/dual', 'userTrades', 'income', + 'commissionRate', + 'apiTradingStatus', // broker endpoints 'apiReferral/ifNewUser', 'apiReferral/customization', @@ -474,6 +521,7 @@ module.exports = class binance extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.001, @@ -498,7 +546,7 @@ module.exports = class binance extends Exchange { 'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision 'newOrderRespType': { 'market': 'FULL', // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills - 'limit': 'RESULT', // we change it from 'ACK' by default to 'RESULT' + 'limit': 'FULL', // we change it from 'ACK' by default to 'FULL' (returns immediately if limit is not hit) }, 'quoteOrderQty': true, // whether market orders support amounts in quote currency 'broker': { @@ -507,6 +555,25 @@ module.exports = class binance extends Exchange { 'future': 'x-xcKtGhcu', 'delivery': 'x-xcKtGhcu', }, + 'fetchPositions': { + 'future': 'fapiPrivateV2GetAccount', // 'fapiPrivateGetPositionRisk' + 'delivery': 'dapiPrivateGetAccount', // 'dapiPrivateGetPositionRisk' + }, + 'accountsByType': { + 'main': 'MAIN', + 'spot': 'MAIN', + 'margin': 'MARGIN', + 'future': 'UMFUTURE', + 'delivery': 'CMFUTURE', + 'mining': 'MINING', + }, + 'typesByAccount': { + 'MAIN': 'spot', + 'MARGIN': 'margin', + 'UMFUTURE': 'future', + 'CMFUTURE': 'delivery', + 'MINING': 'mining', + }, }, // https://binance-docs.github.io/apidocs/spot/en/#error-codes-2 'exceptions': { @@ -564,6 +631,8 @@ module.exports = class binance extends Exchange { '-3010': ExchangeError, // {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."} '-3022': AccountSuspended, // You account's trading is banned. '-4028': BadRequest, // {"code":-4028,"msg":"Leverage 100 is not valid"} + '-3020': InsufficientFunds, // {"code":-3020,"msg":"Transfer out amount exceeds max amount."} + '-3041': InsufficientFunds, // {"code":-3041,"msg":"Balance is not enough"} '-5013': InsufficientFunds, // Asset transfer failed: insufficient balance" }, }); @@ -706,13 +775,14 @@ module.exports = class binance extends Exchange { let fee = undefined; for (let j = 0; j < networkList.length; j++) { const networkItem = networkList[j]; - const name = this.safeString (networkItem, 'name'); - const withdrawFee = this.safeFloat (networkItem, 'withdrawFee'); + const network = this.safeString (networkItem, 'network'); + // const name = this.safeString (networkItem, 'name'); + const withdrawFee = this.safeNumber (networkItem, 'withdrawFee'); const depositEnable = this.safeValue (networkItem, 'depositEnable'); const withdrawEnable = this.safeValue (networkItem, 'withdrawEnable'); isDepositEnabled = isDepositEnabled || depositEnable; isWithdrawEnabled = isWithdrawEnabled || withdrawEnable; - fees[name] = withdrawFee; + fees[network] = withdrawFee; const isDefault = this.safeValue (networkItem, 'isDefault'); if (isDefault || fee === undefined) { fee = withdrawFee; @@ -898,7 +968,7 @@ module.exports = class binance extends Exchange { if (this.options['adjustForTimeDifference']) { await this.loadTimeDifference (); } - const markets = this.safeValue (response, 'symbols'); + const markets = this.safeValue (response, 'symbols', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -963,10 +1033,10 @@ module.exports = class binance extends Exchange { // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } @@ -977,47 +1047,26 @@ module.exports = class binance extends Exchange { const stepSize = this.safeString (filter, 'stepSize'); entry['precision']['amount'] = this.precisionFromString (stepSize); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat2 (filter, 'minNotional', 'notional'); + entry['limits']['cost']['min'] = this.safeNumber2 (filter, 'minNotional', 'notional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot'); @@ -1188,8 +1237,8 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -1202,13 +1251,13 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['used'] = this.safeFloat (balance, 'initialMargin'); - account['total'] = this.safeFloat2 (balance, 'marginBalance', 'balance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['used'] = this.safeString (balance, 'initialMargin'); + account['total'] = this.safeString2 (balance, 'marginBalance', 'balance'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -1261,36 +1310,36 @@ module.exports = class binance extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'openPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'openPrice'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } async fetchStatus (params = {}) { const response = await this.wapiGetSystemStatus (params); - let status = this.safeValue (response, 'status'); + let status = this.safeString (response, 'status'); if (status !== undefined) { - status = (status === 0) ? 'ok' : 'maintenance'; + status = (status === '0') ? 'ok' : 'maintenance'; this.status = this.extend (this.status, { 'status': status, 'updated': this.milliseconds (), @@ -1319,14 +1368,6 @@ module.exports = class binance extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot'); @@ -1381,11 +1422,11 @@ module.exports = class binance extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -1516,8 +1557,11 @@ module.exports = class binance extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -1535,7 +1579,7 @@ module.exports = class binance extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -1548,10 +1592,6 @@ module.exports = class binance extends Exchange { } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } return { 'info': trade, 'timestamp': timestamp, @@ -1670,7 +1710,7 @@ module.exports = class binance extends Exchange { parseOrder (order, market = undefined) { // - // spot + // spot // // { // "symbol": "LTCBTC", @@ -1691,7 +1731,7 @@ module.exports = class binance extends Exchange { // "isWorking": true // } // - // futures + // futures // // { // "symbol": "BTCUSDT", @@ -1709,6 +1749,33 @@ module.exports = class binance extends Exchange { // "updateTime": 1499827319559 // } // + // createOrder with { "newOrderRespType": "FULL" } + // + // { + // "symbol": "BTCUSDT", + // "orderId": 5403233939, + // "orderListId": -1, + // "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e", + // "transactTime": 1617151923742, + // "price": "0.00000000", + // "origQty": "0.00050000", + // "executedQty": "0.00050000", + // "cummulativeQuoteQty": "29.47081500", + // "status": "FILLED", + // "timeInForce": "GTC", + // "type": "MARKET", + // "side": "BUY", + // "fills": [ + // { + // "price": "58941.63000000", + // "qty": "0.00050000", + // "commission": "0.00007050", + // "commissionAsset": "BNB", + // "tradeId": 737466631 + // } + // ] + // } + // const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -1718,80 +1785,26 @@ module.exports = class binance extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); // - Spot/Margin market: cummulativeQuoteQty // - Futures market: cumQuote. // Note this is not the actual cost, since Binance futures uses leverage to calculate margins. - let cost = this.safeFloat2 (order, 'cummulativeQuoteQty', 'cumQuote'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const cost = this.safeNumber2 (order, 'cummulativeQuoteQty', 'cumQuote'); const id = this.safeString (order, 'orderId'); let type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - if (this.options['parseOrderToPrecision']) { - price = parseFloat (this.priceToPrecision (symbol, price)); - } - } - } - } - } else if (type === 'limit_maker') { + if (type === 'limit_maker') { type = 'limit'; } const side = this.safeStringLower (order, 'side'); - let fee = undefined; - let trades = undefined; - const fills = this.safeValue (order, 'fills'); - if (fills !== undefined) { - trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - if (this.options['parseOrderToPrecision']) { - average = parseFloat (this.priceToPrecision (symbol, average)); - } - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const fills = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (fills, market); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = (type === 'limit_maker') || (timeInForce === 'GTX'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1807,13 +1820,13 @@ module.exports = class binance extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1860,8 +1873,11 @@ module.exports = class binance extends Exchange { } else { request['newClientOrderId'] = clientOrderId; } - if (market['spot']) { + if ((orderType === 'spot') || (orderType === 'margin')) { request['newOrderRespType'] = this.safeValue (this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills + } else { + // delivery and future + request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK" } // additional required fields depending on the order type let timeInForceIsRequired = false; @@ -1891,7 +1907,7 @@ module.exports = class binance extends Exchange { if (uppercaseType === 'MARKET') { const quoteOrderQty = this.safeValue (this.options, 'quoteOrderQty', false); if (quoteOrderQty) { - const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty'); + const quoteOrderQty = this.safeNumber (params, 'quoteOrderQty'); const precision = market['precision']['price']; if (quoteOrderQty !== undefined) { request['quoteOrderQty'] = this.decimalToPrecision (quoteOrderQty, TRUNCATE, precision, this.precisionMode); @@ -1911,7 +1927,7 @@ module.exports = class binance extends Exchange { } else if ((uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT')) { stopPriceIsRequired = true; quantityIsRequired = true; - if (market['future']) { + if (market['future'] || market['delivery']) { priceIsRequired = true; } } else if ((uppercaseType === 'STOP_LOSS_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) { @@ -1934,7 +1950,7 @@ module.exports = class binance extends Exchange { stopPriceIsRequired = true; } else if (uppercaseType === 'TRAILING_STOP_MARKET') { quantityIsRequired = true; - const callbackRate = this.safeFloat (params, 'callbackRate'); + const callbackRate = this.safeNumber (params, 'callbackRate'); if (callbackRate === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a callbackRate extra param for a ' + type + ' order'); } @@ -1952,7 +1968,7 @@ module.exports = class binance extends Exchange { request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -2168,10 +2184,15 @@ module.exports = class binance extends Exchange { } } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.fetchBalance (params); - const info = this.safeValue (response, 'info', {}); + const defaultType = this.safeString (this.options, 'defaultType', 'future'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + const options = this.safeValue (this.options, 'fetchPositions', {}); + const defaultMethod = (type === 'delivery') ? 'dapiPrivateGetAccount' : 'fapiPrivateV2GetAccount'; + const method = this.safeString (options, type, defaultMethod); + const response = await this[method] (params); // // futures, delivery // @@ -2214,9 +2235,44 @@ module.exports = class binance extends Exchange { // ] // } // - const positions = this.safeValue2 (info, 'positions', 'userAssets', []); - // todo unify parsePosition/parsePositions - return positions; + // fapiPrivateGetPositionRisk, dapiPrivateGetPositionRisk + // + // [ + // { + // symbol: 'XRPUSD_210625', + // positionAmt: '0', + // entryPrice: '0.00000000', + // markPrice: '0.00000000', + // unRealizedProfit: '0.00000000', + // liquidationPrice: '0', + // leverage: '20', + // maxQty: '500000', + // marginType: 'cross', + // isolatedMargin: '0.00000000', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0', + // isolatedWallet: '0' + // }, + // { + // symbol: 'BTCUSD_210326', + // positionAmt: '1', + // entryPrice: '60665.79999885', + // markPrice: '60696.76856843', + // unRealizedProfit: '0.00000084', + // liquidationPrice: '58034.68208092', + // leverage: '20', + // maxQty: '50', + // marginType: 'isolated', + // isolatedMargin: '0.00008345', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0.00164753', + // isolatedWallet: '0.00008261' + // }, + // ] + // + return this.safeValue (response, 'positions', response); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -2354,7 +2410,7 @@ module.exports = class binance extends Exchange { // const fee = { 'currency': earnedCurrency, - 'cost': this.safeFloat (trade, 'serviceChargeAmount'), + 'cost': this.safeNumber (trade, 'serviceChargeAmount'), }; let symbol = undefined; let amount = undefined; @@ -2362,13 +2418,13 @@ module.exports = class binance extends Exchange { let side = undefined; if (tradedCurrencyIsQuote) { symbol = applicantSymbol; - amount = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); - cost = this.safeFloat (trade, 'amount'); + amount = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); + cost = this.safeNumber (trade, 'amount'); side = 'buy'; } else { symbol = tradedCurrency + '/' + earnedCurrency; - amount = this.safeFloat (trade, 'amount'); - cost = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); + amount = this.safeNumber (trade, 'amount'); + cost = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); side = 'sell'; } let price = undefined; @@ -2541,8 +2597,8 @@ module.exports = class binance extends Exchange { } } const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'transactionFee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'transactionFee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -2569,6 +2625,151 @@ module.exports = class binance extends Exchange { }; } + parseTransferStatus (status) { + const statuses = { + 'CONFIRMED': 'ok', + }; + return this.safeString (statuses, status, status); + } + + parseTransfer (transfer, currency = undefined) { + // + // transfer + // + // { + // "tranId":13526853623 + // } + // + // fetchTransfers + // + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // } + // + const id = this.safeString (transfer, 'tranId'); + const currencyId = this.safeString (transfer, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const amount = this.safeNumber (transfer, 'amount'); + const type = this.safeString (transfer, 'type'); + let fromAccount = undefined; + let toAccount = undefined; + const typesByAccount = this.safeValue (this.options, 'typesByAccount', {}); + if (type !== undefined) { + const parts = type.split ('_'); + fromAccount = this.safeValue (parts, 0); + toAccount = this.safeValue (parts, 1); + fromAccount = this.safeString (typesByAccount, fromAccount, fromAccount); + toAccount = this.safeString (typesByAccount, toAccount, toAccount); + } + const timestamp = this.safeInteger (transfer, 'timestamp'); + const status = this.parseTransferStatus (this.safeString (transfer, 'status')); + return { + 'info': transfer, + 'id': id, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'currency': code, + 'amount': amount, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': status, + }; + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount, fromAccount); + const toId = this.safeString (accountsByType, toAccount, toAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'asset': currency['id'], + 'amount': this.currencyToPrecision (code, amount), + 'type': type, + }; + const response = await this.sapiPostAssetTransfer (this.extend (request, params)); + // + // { + // "tranId":13526853623 + // } + // + const transfer = this.parseTransfer (response, currency); + return this.extend (transfer, { + 'amount': amount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + }); + } + + async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const defaultType = this.safeString2 (this.options, 'fetchTransfers', 'defaultType', 'spot'); + const fromAccount = this.safeString (params, 'fromAccount', defaultType); + const defaultTo = (fromAccount === 'future') ? 'spot' : 'future'; + const toAccount = this.safeString (params, 'toAccount', defaultTo); + let type = this.safeString (params, 'type'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + if (type === undefined) { + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount parameter must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount parameter must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'type': type, + }; + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['size'] = limit; + } + const response = await this.sapiGetAssetTransfer (this.extend (request, params)); + // + // { + // total: 3, + // rows: [ + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // }, + // ] + // } + // + const rows = this.safeValue (response, 'rows', []); + return this.parseTransfers (rows, currency, since, limit); + } + async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -2631,7 +2832,7 @@ module.exports = class binance extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (detail[id], 'withdrawFee'); + withdrawFees[code] = this.safeNumber (detail[id], 'withdrawFee'); } return { 'withdraw': withdrawFees, @@ -2678,8 +2879,8 @@ module.exports = class binance extends Exchange { return { 'info': fee, 'symbol': symbol, - 'maker': this.safeFloat (fee, 'maker'), - 'taker': this.safeFloat (fee, 'taker'), + 'maker': this.safeNumber (fee, 'maker'), + 'taker': this.safeNumber (fee, 'taker'), }; } @@ -2741,7 +2942,6 @@ module.exports = class binance extends Exchange { if (api === 'wapi') { url += '.html'; } - const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); if (path === 'historicalTrades') { if (this.apiKey) { headers = { @@ -2750,19 +2950,22 @@ module.exports = class binance extends Exchange { } else { throw new AuthenticationError (this.id + ' historicalTrades endpoint requires `apiKey` credential'); } - } else if (userDataStream) { + } + const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); + if (userDataStream) { if (this.apiKey) { // v1 special case for userDataStream - body = this.urlencode (params); headers = { 'X-MBX-APIKEY': this.apiKey, 'Content-Type': 'application/x-www-form-urlencoded', }; + if (method !== 'GET') { + body = this.urlencode (params); + } } else { throw new AuthenticationError (this.id + ' userDataStream endpoint requires `apiKey` credential'); } - } - if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { + } else if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { this.checkRequiredCredentials (); let query = undefined; const recvWindow = this.safeInteger (this.options, 'recvWindow', 5000); @@ -2794,13 +2997,8 @@ module.exports = class binance extends Exchange { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } } else { - // userDataStream endpoints are public, but POST, PUT, DELETE - // therefore they don't accept URL query arguments - // https://github.com/ccxt/ccxt/issues/5224 - if (!userDataStream) { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } + if (Object.keys (params).length) { + url += '?' + this.urlencode (params); } } return { 'url': url, 'method': method, 'body': body, 'headers': headers }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bit2c.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bit2c.js index a4d60733a..1f58d3f75 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bit2c.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bit2c.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, InvalidNonce, AuthenticationError, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -155,12 +156,12 @@ module.exports = class bit2c extends Exchange { const currencyId = this.currencyId (code); const uppercase = currencyId.toUpperCase (); if (uppercase in balance) { - account['free'] = this.safeFloat (balance, 'AVAILABLE_' + uppercase); - account['total'] = this.safeFloat (balance, uppercase); + account['free'] = this.safeString (balance, 'AVAILABLE_' + uppercase); + account['total'] = this.safeString (balance, uppercase); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -179,22 +180,22 @@ module.exports = class bit2c extends Exchange { }; const ticker = await this.publicGetExchangesPairTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const averagePrice = this.safeFloat (ticker, 'av'); - const baseVolume = this.safeFloat (ticker, 'a'); + const averagePrice = this.safeNumber (ticker, 'av'); + const baseVolume = this.safeNumber (ticker, 'a'); let quoteVolume = undefined; if (baseVolume !== undefined && averagePrice !== undefined) { quoteVolume = baseVolume * averagePrice; } - const last = this.safeFloat (ticker, 'll'); + const last = this.safeNumber (ticker, 'll'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'h'), + 'bid': this.safeNumber (ticker, 'h'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'l'), + 'ask': this.safeNumber (ticker, 'l'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -276,14 +277,8 @@ module.exports = class bit2c extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -296,7 +291,7 @@ module.exports = class bit2c extends Exchange { } const id = this.safeString (order, 'id'); const status = this.safeString (order, 'status'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -313,12 +308,12 @@ module.exports = class bit2c extends Exchange { 'amount': amount, 'filled': undefined, 'remaining': undefined, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -344,16 +339,16 @@ module.exports = class bit2c extends Exchange { parseTrade (trade, market = undefined) { let timestamp = undefined; let id = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let orderId = undefined; let feeCost = undefined; let side = undefined; const reference = this.safeString (trade, 'reference'); if (reference !== undefined) { timestamp = this.safeTimestamp (trade, 'ticks'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'firstAmount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'firstAmount'); const reference_parts = reference.split ('|'); // reference contains 'pair|orderId|tradeId' if (market === undefined) { const marketId = this.safeString (trade, 'pair'); @@ -371,12 +366,12 @@ module.exports = class bit2c extends Exchange { } else if (side === 1) { side = 'sell'; } - feeCost = this.safeFloat (trade, 'feeAmount'); + feeCost = this.safeNumber (trade, 'feeAmount'); } else { timestamp = this.safeTimestamp (trade, 'date'); id = this.safeString (trade, 'tid'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'amount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'amount'); side = this.safeValue (trade, 'isBid'); if (side !== undefined) { if (side) { @@ -390,6 +385,9 @@ module.exports = class bit2c extends Exchange { if (market !== undefined) { symbol = market['symbol']; } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -402,7 +400,7 @@ module.exports = class bit2c extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': { 'cost': feeCost, 'currency': 'NIS', diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbank.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbank.js index d357531d7..c3626b01f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbank.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbank.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -78,21 +79,23 @@ module.exports = class bitbank extends Exchange { }, }, 'markets': { + 'BAT/JPY': { 'id': 'bat_jpy', 'symbol': 'BAT/JPY', 'base': 'BAT', 'quote': 'JPY', 'baseId': 'bat', 'quoteId': 'jpy' }, + 'BAT/BTC': { 'id': 'bat_btc', 'symbol': 'BAT/BTC', 'base': 'BAT', 'quote': 'BTC', 'baseId': 'bat', 'quoteId': 'btc' }, 'BCH/BTC': { 'id': 'bcc_btc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'baseId': 'bcc', 'quoteId': 'btc' }, 'BCH/JPY': { 'id': 'bcc_jpy', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bcc', 'quoteId': 'jpy' }, + 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, + 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, + 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, + 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, + 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, 'MONA/BTC': { 'id': 'mona_btc', 'symbol': 'MONA/BTC', 'base': 'MONA', 'quote': 'BTC', 'baseId': 'mona', 'quoteId': 'btc' }, 'MONA/JPY': { 'id': 'mona_jpy', 'symbol': 'MONA/JPY', 'base': 'MONA', 'quote': 'JPY', 'baseId': 'mona', 'quoteId': 'jpy' }, 'QTUM/BTC': { 'id': 'qtum_btc', 'symbol': 'QTUM/BTC', 'base': 'QTUM', 'quote': 'BTC', 'baseId': 'qtum', 'quoteId': 'btc' }, 'QTUM/JPY': { 'id': 'qtum_jpy', 'symbol': 'QTUM/JPY', 'base': 'QTUM', 'quote': 'JPY', 'baseId': 'qtum', 'quoteId': 'jpy' }, - 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, - 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, - 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, - 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, - 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, - 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, - 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, - 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, 'XLM/BTC': { 'id': 'xlm_btc', 'symbol': 'XLM/BTC', 'base': 'XLM', 'quote': 'BTC', 'baseId': 'xlm', 'quoteId': 'btc' }, + 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, + 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, + 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, }, 'fees': { 'trading': { @@ -141,16 +144,16 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -160,7 +163,7 @@ module.exports = class bitbank extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -196,18 +199,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; feeCurrency = market['quote']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'transaction_id', 'trade_id'); const takerOrMaker = this.safeString (trade, 'maker_taker'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee_amount_quote'); + const feeCost = this.safeNumber (trade, 'fee_amount_quote'); if (feeCost !== undefined) { fee = { 'currency': feeCurrency, @@ -259,11 +259,11 @@ module.exports = class bitbank extends Exchange { // return [ this.safeInteger (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -314,14 +314,13 @@ module.exports = class bitbank extends Exchange { const balance = assets[i]; const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'free_amount'), - 'used': this.safeFloat (balance, 'locked_amount'), - 'total': this.safeFloat (balance, 'onhand_amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'free_amount'); + account['used'] = this.safeString (balance, 'locked_amount'); + account['total'] = this.safeString (balance, 'onhand_amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -346,21 +345,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (order, 'ordered_at'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'start_amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const average = this.safeFloat (order, 'average_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'start_amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const average = this.safeNumber (order, 'average_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -374,7 +367,7 @@ module.exports = class bitbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, @@ -382,7 +375,7 @@ module.exports = class bitbank extends Exchange { 'trades': undefined, 'fee': undefined, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbay.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbay.js index 4f502e934..760fc7aa2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbay.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitbay.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -278,8 +279,8 @@ module.exports = class bitbay extends Exchange { if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) { fees = this.safeValue (this.fees, 'fiat', {}); } - const maker = this.safeFloat (fees, 'maker'); - const taker = this.safeFloat (fees, 'taker'); + const maker = this.safeNumber (fees, 'maker'); + const taker = this.safeNumber (fees, 'taker'); // todo: check that the limits have ben interpreted correctly // todo: parse the fees page result.push ({ @@ -295,7 +296,7 @@ module.exports = class bitbay extends Exchange { 'taker': taker, 'limits': { 'amount': { - 'min': this.safeFloat (first, 'minOffer'), + 'min': this.safeNumber (first, 'minOffer'), 'max': undefined, }, 'price': { @@ -303,7 +304,7 @@ module.exports = class bitbay extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (second, 'minOffer'), + 'min': this.safeNumber (second, 'minOffer'), 'max': undefined, }, }, @@ -343,16 +344,10 @@ module.exports = class bitbay extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (order, 'time'); - const amount = this.safeFloat (order, 'startAmount'); - const remaining = this.safeFloat (order, 'currentAmount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } + const amount = this.safeNumber (order, 'startAmount'); + const remaining = this.safeNumber (order, 'currentAmount'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'info': order, @@ -365,16 +360,16 @@ module.exports = class bitbay extends Exchange { 'timeInForce': undefined, 'postOnly': postOnly, 'side': this.safeStringLower (order, 'offerType'), - 'price': this.safeFloat (order, 'rate'), + 'price': this.safeNumber (order, 'rate'), 'stopPrice': undefined, 'amount': amount, 'cost': undefined, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'average': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -427,11 +422,11 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lockedFunds'); - account['free'] = this.safeFloat (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'lockedFunds'); + account['free'] = this.safeString (balance, 'availableFunds'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -450,22 +445,22 @@ module.exports = class bitbay extends Exchange { }; const ticker = await this.publicGetIdTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'volume'); - const vwap = this.safeFloat (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max'), + 'low': this.safeNumber (ticker, 'min'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -474,7 +469,7 @@ module.exports = class bitbay extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), + 'average': this.safeNumber (ticker, 'average'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -775,7 +770,7 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const change = this.safeValue (item, 'change', {}); - let amount = this.safeFloat (change, 'total'); + let amount = this.safeNumber (change, 'total'); let direction = 'in'; if (amount < 0) { direction = 'out'; @@ -787,9 +782,9 @@ module.exports = class bitbay extends Exchange { const referenceId = this.safeString (item, 'detailId'); const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const fundsBefore = this.safeValue (item, 'fundsBefore', {}); - const before = this.safeFloat (fundsBefore, 'total'); + const before = this.safeNumber (fundsBefore, 'total'); const fundsAfter = this.safeValue (item, 'fundsAfter', {}); - const after = this.safeFloat (fundsAfter, 'total'); + const after = this.safeNumber (fundsAfter, 'total'); return { 'info': item, 'id': id, @@ -846,11 +841,11 @@ module.exports = class bitbay extends Exchange { const first = this.safeValue (ohlcv, 1, {}); return [ this.safeInteger (ohlcv, 0), - this.safeFloat (first, 'o'), - this.safeFloat (first, 'h'), - this.safeFloat (first, 'l'), - this.safeFloat (first, 'c'), - this.safeFloat (first, 'v'), + this.safeNumber (first, 'o'), + this.safeNumber (first, 'h'), + this.safeNumber (first, 'l'), + this.safeNumber (first, 'c'), + this.safeNumber (first, 'v'), ]; } @@ -933,15 +928,12 @@ module.exports = class bitbay extends Exchange { if (wasTaker !== undefined) { takerOrMaker = wasTaker ? 'taker' : 'maker'; } - const price = this.safeFloat2 (trade, 'rate', 'r'); - const amount = this.safeFloat2 (trade, 'amount', 'a'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'commissionValue'); + const priceString = this.safeString2 (trade, 'rate', 'r'); + const amountString = this.safeString2 (trade, 'amount', 'a'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'commissionValue'); const marketId = this.safeString (trade, 'market'); market = this.safeMarket (marketId, market, '-'); const symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex.js index 6d34687ff..1d7643454 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { NotSupported, RateLimitExceeded, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, InvalidNonce, BadSymbol } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -45,6 +46,7 @@ module.exports = class bitfinex extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': '1m', @@ -158,6 +160,7 @@ module.exports = class bitfinex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'maker': 0.1 / 100, @@ -344,6 +347,8 @@ module.exports = class bitfinex extends Exchange { 'No summary found.': ExchangeError, // fetchTradingFees (summary) endpoint can give this vague error message 'Cannot evaluate your available balance, please try again': ExchangeNotAvailable, 'Unknown symbol': BadSymbol, + 'Cannot complete transfer. Exchange balance insufficient.': InsufficientFunds, + 'Momentary balance check. Please wait few seconds and try the transfer again.': ExchangeError, }, 'broad': { 'Invalid X-BFX-SIGNATURE': AuthenticationError, @@ -441,6 +446,15 @@ module.exports = class bitfinex extends Exchange { 'limit': 'exchange limit', 'market': 'exchange market', }, + 'accountsByType': { + 'spot': 'exchange', + 'margin': 'trading', + 'funding': 'deposit', + 'exchange': 'exchange', + 'trading': 'trading', + 'deposit': 'deposit', + 'derivatives': 'trading', + }, }, }); } @@ -454,7 +468,7 @@ module.exports = class bitfinex extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdraw[code] = this.safeFloat (fees, id); + withdraw[code] = this.safeNumber (fees, id); } return { 'info': response, @@ -490,14 +504,31 @@ module.exports = class bitfinex extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } async fetchMarkets (params = {}) { const ids = await this.publicGetSymbols (); + // + // [ "btcusd", "ltcusd", "ltcbtc" ] + // const details = await this.publicGetSymbolsDetails (); + // + // [ + // { + // "pair":"btcusd", + // "price_precision":5, + // "initial_margin":"10.0", + // "minimum_margin":"5.0", + // "maximum_order_size":"2000.0", + // "minimum_order_size":"0.0002", + // "expiration":"NA", + // "margin":true + // }, + // ] + // const result = []; for (let i = 0; i < details.length; i++) { const market = details[i]; @@ -528,8 +559,8 @@ module.exports = class bitfinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -540,6 +571,7 @@ module.exports = class bitfinex extends Exchange { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -548,6 +580,8 @@ module.exports = class bitfinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': true, + 'type': 'spot', + 'margin': margin, 'precision': precision, 'limits': limits, 'info': market, @@ -572,40 +606,15 @@ module.exports = class bitfinex extends Exchange { return this.decimalToPrecision (price, TRUNCATE, 8, DECIMAL_PLACES); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - const code = market[key]; - const currency = this.safeValue (this.currencies, code); - if (currency !== undefined) { - const precision = this.safeInteger (currency, 'precision'); - if (precision !== undefined) { - cost = parseFloat (this.currencyToPrecision (code, cost)); - } - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); - const types = { - 'exchange': 'exchange', - 'deposit': 'funding', - 'trading': 'margin', - }; - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } const query = this.omit (params, 'type'); const response = await this.privatePostBalances (query); // [ { type: 'deposit', @@ -621,12 +630,16 @@ module.exports = class bitfinex extends Exchange { // amount: '0.0005', // available: '0.0005' } ], const result = { 'info': response }; + const isDerivative = requestedType === 'derivatives'; for (let i = 0; i < response.length; i++) { const balance = response[i]; const type = this.safeString (balance, 'type'); - const parsedType = this.safeString (types, type); - if ((parsedType === balanceType) || (type === balanceType)) { - const currencyId = this.safeString (balance, 'currency'); + const currencyId = this.safeStringLower (balance, 'currency', ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { const code = this.safeCurrencyCode (currencyId); // bitfinex had BCH previously, now it's BAB, but the old // BCH symbol is kept for backward-compatibility @@ -635,13 +648,80 @@ module.exports = class bitfinex extends Exchange { // https://github.com/ccxt/ccxt/issues/4989 if (!(code in result)) { const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currencyId = this.currencyId (code); + const fromCurrencyId = this.convertDerivativesId (currencyId, fromAccount); + const toCurrencyId = this.convertDerivativesId (currencyId, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'walletfrom': fromId, + 'walletto': toId, + }; + const response = await this.privatePostTransfer (this.extend (request, params)); + // [ + // { + // status: 'success', + // message: '0.0001 Bitcoin transfered from Margin to Exchange' + // } + // ] + const result = this.safeValue (response, 0); + const status = this.safeString (result, 'status'); + const message = this.safeString (result, 'message'); + if (message === undefined) { + throw new ExchangeError (this.id + ' transfer failed'); + } + // [{"status":"error","message":"Momentary balance check. Please wait few seconds and try the transfer again."}] + if (status === 'error') { + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + return { + 'info': response, + 'status': status, + 'amount': requestedAmount, + 'code': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'timestamp': undefined, + 'datetime': undefined, + }; + } + + convertDerivativesId (currencyId, type) { + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if ((type !== 'derivatives' && type !== 'trading' && type !== 'margin') && isDerivativeCode) { + currencyId = currencyId.slice (0, start); + } else if (type === 'derivatives' && !isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + return currencyId; } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -680,7 +760,7 @@ module.exports = class bitfinex extends Exchange { } parseTicker (ticker, market = undefined) { - let timestamp = this.safeFloat (ticker, 'timestamp'); + let timestamp = this.safeNumber (ticker, 'timestamp'); if (timestamp !== undefined) { timestamp *= 1000; } @@ -703,16 +783,16 @@ module.exports = class bitfinex extends Exchange { } } } - const last = this.safeFloat (ticker, 'last_price'); + const last = this.safeNumber (ticker, 'last_price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -721,8 +801,8 @@ module.exports = class bitfinex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'mid'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'mid'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -730,24 +810,21 @@ module.exports = class bitfinex extends Exchange { parseTrade (trade, market) { const id = this.safeString (trade, 'tid'); - let timestamp = this.safeFloat (trade, 'timestamp'); + let timestamp = this.safeNumber (trade, 'timestamp'); if (timestamp !== undefined) { timestamp = parseInt (timestamp) * 1000; } const type = undefined; const side = this.safeStringLower (trade, 'type'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; if ('fee_amount' in trade) { - const feeCost = -this.safeFloat (trade, 'fee_amount'); + const feeCost = -this.safeNumber (trade, 'fee_amount'); const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { @@ -862,6 +939,30 @@ module.exports = class bitfinex extends Exchange { } parseOrder (order, market = undefined) { + // + // { + // id: 57334010955, + // cid: 1611584840966, + // cid_date: null, + // gid: null, + // symbol: 'ltcbtc', + // exchange: null, + // price: '0.0042125', + // avg_execution_price: '0.0042097', + // side: 'sell', + // type: 'exchange market', + // timestamp: '1611584841.0', + // is_live: false, + // is_cancelled: false, + // is_hidden: 0, + // oco_order: 0, + // was_forced: false, + // original_amount: '0.205176', + // remaining_amount: '0.0', + // executed_amount: '0.205176', + // src: 'web' + // } + // const side = this.safeString (order, 'side'); const open = this.safeValue (order, 'is_live'); const canceled = this.safeValue (order, 'is_cancelled'); @@ -873,30 +974,17 @@ module.exports = class bitfinex extends Exchange { } else { status = 'closed'; } - let symbol = undefined; - if (market === undefined) { - const marketId = this.safeStringUpper (order, 'symbol'); - if (marketId !== undefined) { - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } - } - } - if (market !== undefined) { - symbol = market['symbol']; - } - let orderType = order['type']; + const marketId = this.safeStringUpper (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market); + let orderType = this.safeString (order, 'type', ''); const exchange = orderType.indexOf ('exchange ') >= 0; if (exchange) { const parts = order['type'].split (' '); orderType = parts[1]; } - let timestamp = this.safeFloat (order, 'timestamp'); - if (timestamp !== undefined) { - timestamp = parseInt (timestamp) * 1000; - } + const timestamp = this.safeTimestamp (order, 'timestamp'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -908,17 +996,17 @@ module.exports = class bitfinex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': side, - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_execution_price'), - 'amount': this.safeFloat (order, 'original_amount'), - 'remaining': this.safeFloat (order, 'remaining_amount'), - 'filled': this.safeFloat (order, 'executed_amount'), + 'average': this.safeNumber (order, 'avg_execution_price'), + 'amount': this.safeNumber (order, 'original_amount'), + 'remaining': this.safeNumber (order, 'remaining_amount'), + 'filled': this.safeNumber (order, 'executed_amount'), 'status': status, 'fee': undefined, 'cost': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -973,11 +1061,11 @@ module.exports = class bitfinex extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -1125,11 +1213,11 @@ module.exports = class bitfinex extends Exchange { // "timestamp_created": "1561716066.0" // } // - let timestamp = this.safeFloat (transaction, 'timestamp_created'); + let timestamp = this.safeNumber (transaction, 'timestamp_created'); if (timestamp !== undefined) { timestamp = parseInt (timestamp * 1000); } - let updated = this.safeFloat (transaction, 'timestamp'); + let updated = this.safeNumber (transaction, 'timestamp'); if (updated !== undefined) { updated = parseInt (updated * 1000); } @@ -1137,7 +1225,7 @@ module.exports = class bitfinex extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const type = this.safeStringLower (transaction, 'type'); // DEPOSIT or WITHDRAWAL const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -1150,7 +1238,7 @@ module.exports = class bitfinex extends Exchange { 'address': this.safeString (transaction, 'address'), // todo: this is actually the tag for XRP transfers (the address is missing) 'tag': undefined, // refix it properly for the tag from description 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -1204,7 +1292,7 @@ module.exports = class bitfinex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex2.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex2.js index b47da9faf..9313f2025 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex2.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitfinex2.js @@ -286,6 +286,15 @@ module.exports = class bitfinex2 extends bitfinex { 'JPY': 'JPY', 'GBP': 'GBP', }, + // actually the correct names unlike the v1 + // we don't want to extend this with accountsByType in v1 + 'v2AccountsByType': { + 'spot': 'exchange', + 'exchange': 'exchange', + 'funding': 'funding', + 'margin': 'margin', + 'derivatives': 'margin', + }, }, 'exceptions': { 'exact': { @@ -367,8 +376,8 @@ module.exports = class bitfinex2 extends bitfinex { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -379,6 +388,7 @@ module.exports = class bitfinex2 extends bitfinex { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -393,6 +403,7 @@ module.exports = class bitfinex2 extends bitfinex { 'type': type, 'swap': false, 'spot': spot, + 'margin': margin, 'futures': futures, }); } @@ -505,7 +516,7 @@ module.exports = class bitfinex2 extends bitfinex { const ids = this.safeValue (response, 0, []); const result = {}; for (let i = 0; i < ids.length; i++) { - let id = ids[i]; + const id = ids[i]; const code = this.safeCurrencyCode (id); const label = this.safeValue (indexed['label'], id, []); const name = this.safeString (label, 1); @@ -513,13 +524,14 @@ module.exports = class bitfinex2 extends bitfinex { const type = this.safeString (pool, 1); const feeValues = this.safeValue (indexed['fees'], id, []); const fees = this.safeValue (feeValues, 1, []); - const fee = this.safeFloat (fees, 1); + const fee = this.safeNumber (fees, 1); + const undl = this.safeValue (indexed['undl'], id, []); const precision = 8; // default precision, todo: fix "magic constants" - id = 'f' + id; + const fid = 'f' + id; result[code] = { - 'id': id, + 'id': fid, 'code': code, - 'info': [ id, label, pool, feeValues ], + 'info': [ id, label, pool, feeValues, undl ], 'type': type, 'name': name, 'active': true, @@ -550,40 +562,117 @@ module.exports = class bitfinex2 extends bitfinex { async fetchBalance (params = {}) { // this api call does not return the 'used' amount - use the v1 version instead (which also returns zero balances) + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 await this.loadMarkets (); - const response = await this.privatePostAuthRWallets (params); - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } + const isDerivative = requestedType === 'derivatives'; + const query = this.omit (params, 'type'); + const response = await this.privatePostAuthRWallets (query); const result = { 'info': response }; - for (let b = 0; b < response.length; b++) { - const balance = response[b]; - const accountType = balance[0]; - let currency = balance[1]; - const total = balance[2]; - const available = balance[4]; - if (accountType === balanceType) { - if (currency[0] === 't') { - currency = currency.slice (1); - } - const code = this.safeCurrencyCode (currency); + for (let i = 0; i < response.length; i++) { + const balance = response[i]; + const type = this.safeString (balance, 0); + const currencyId = this.safeStringLower (balance, 1, ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { + const code = this.safeCurrencyCode (currencyId); const account = this.account (); - // do not fill in zeroes and missing values in the parser - // rewrite and unify the following to use the unified parseBalance - account['total'] = total; - if (!available) { - if (available === 0) { - account['free'] = 0; - account['used'] = total; - } else { - account['free'] = total; - } - } else { - account['free'] = available; - account['used'] = account['total'] - account['free']; - } + account['total'] = this.safeString (balance, 2); + account['free'] = this.safeString (balance, 4); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currency = this.currency (code); + const fromCurrencyId = this.convertDerivativesId (currency, fromAccount); + const toCurrencyId = this.convertDerivativesId (currency, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + // this request is slightly different from v1 fromAccount -> from + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'from': fromId, + 'to': toId, + }; + const response = await this.privatePostAuthWTransfer (this.extend (request, params)); + // [1616451183763,"acc_tf",null,null,[1616451183763,"exchange","margin",null,"UST","UST",null,1],null,"SUCCESS","1.0 Tether USDt transfered from Exchange to Margin"] + const timestamp = this.safeInteger (response, 0); + // ["error",10001,"Momentary balance check. Please wait few seconds and try the transfer again."] + const error = this.safeString (response, 0); + if (error === 'error') { + const message = this.safeString (response, 2, ''); + // same message as in v1 + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + const info = this.safeValue (response, 4); + const fromResponse = this.safeString (info, 1); + const toResponse = this.safeString (info, 2); + const toCode = this.safeCurrencyCode (this.safeString (info, 5)); + const success = this.safeString (response, 6); + const status = (success === 'SUCCESS') ? 'ok' : undefined; + return { + 'info': response, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'status': status, + 'amount': requestedAmount, + 'code': toCode, + 'fromAccount': fromResponse, + 'toAccount': toResponse, + }; + } + + convertDerivativesId (currency, type) { + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 + // { + // id: 'fUSTF0', + // code: 'USTF0', + // info: [ 'USTF0', [], [], [], [ 'USTF0', 'UST' ] ], + const info = this.safeValue (currency, 'info'); + const transferId = this.safeString (info, 0); + const underlying = this.safeValue (info, 4, []); + let currencyId = undefined; + if (type === 'derivatives') { + currencyId = this.safeString (underlying, 0, transferId); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if (!isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + } else if (type !== 'margin') { + currencyId = this.safeString (underlying, 1, transferId); + } else { + currencyId = transferId; + } + return currencyId; } async fetchOrder (id, symbol = undefined, params = {}) { @@ -613,9 +702,10 @@ module.exports = class bitfinex2 extends bitfinex { const priceIndex = (fullRequest['precision'] === 'R0') ? 1 : 0; for (let i = 0; i < orderbook.length; i++) { const order = orderbook[i]; - const price = order[priceIndex]; - const amount = Math.abs (order[2]); - const side = (order[2] > 0) ? 'bids' : 'asks'; + const price = this.safeNumber (order, priceIndex); + const signedAmount = this.safeNumber (order, 2); + const amount = Math.abs (signedAmount); + const side = (signedAmount > 0) ? 'bids' : 'asks'; result[side].push ([ price, amount ]); } result['bids'] = this.sortBy (result['bids'], 0, true); @@ -630,26 +720,26 @@ module.exports = class bitfinex2 extends bitfinex { symbol = market['symbol']; } const length = ticker.length; - const last = ticker[length - 4]; + const last = this.safeNumber (ticker, length - 4); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': ticker[length - 2], - 'low': ticker[length - 1], - 'bid': ticker[length - 10], + 'high': this.safeNumber (ticker, length - 2), + 'low': this.safeNumber (ticker, length - 1), + 'bid': this.safeNumber (ticker, length - 10), 'bidVolume': undefined, - 'ask': ticker[length - 8], + 'ask': this.safeNumber (ticker, length - 8), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': ticker[length - 6], - 'percentage': ticker[length - 5] * 100, + 'change': this.safeNumber (ticker, length - 6), + 'percentage': this.safeNumber (ticker, length - 5) * 100, 'average': undefined, - 'baseVolume': ticker[length - 3], + 'baseVolume': this.safeNumber (ticker, length - 3), 'quoteVolume': undefined, 'info': ticker, }; @@ -738,12 +828,12 @@ module.exports = class bitfinex2 extends bitfinex { // const tradeLength = trade.length; const isPrivate = (tradeLength > 5); - const id = trade[0].toString (); + const id = this.safeString (trade, 0); const amountIndex = isPrivate ? 4 : 2; - let amount = trade[amountIndex]; + let amount = this.safeNumber (trade, amountIndex); let cost = undefined; const priceIndex = isPrivate ? 5 : 3; - const price = trade[priceIndex]; + const price = this.safeNumber (trade, priceIndex); let side = undefined; let orderId = undefined; let takerOrMaker = undefined; @@ -751,7 +841,7 @@ module.exports = class bitfinex2 extends bitfinex { let fee = undefined; let symbol = undefined; const timestampIndex = isPrivate ? 2 : 1; - const timestamp = trade[timestampIndex]; + const timestamp = this.safeInteger (trade, timestampIndex); if (isPrivate) { const marketId = trade[1]; if (marketId in this.markets_by_id) { @@ -760,10 +850,12 @@ module.exports = class bitfinex2 extends bitfinex { } else { symbol = this.parseSymbol (marketId); } - orderId = trade[3].toString (); - takerOrMaker = (trade[8] === 1) ? 'maker' : 'taker'; - let feeCost = trade[9]; - const feeCurrency = this.safeCurrencyCode (trade[10]); + orderId = this.safeString (trade, 3); + const maker = this.safeInteger (trade, 8); + takerOrMaker = (maker === 1) ? 'maker' : 'taker'; + let feeCost = this.safeNumber (trade, 9); + const feeCurrencyId = this.safeString (trade, 10); + const feeCurrency = this.safeCurrencyCode (feeCurrencyId); if (feeCost !== undefined) { feeCost = -feeCost; if (symbol in this.markets) { @@ -904,10 +996,10 @@ module.exports = class bitfinex2 extends bitfinex { // https://github.com/ccxt/ccxt/issues/6686 // const timestamp = this.safeTimestamp (order, 5); const timestamp = this.safeInteger (order, 5); - const remaining = Math.abs (this.safeFloat (order, 6)); - const amount = Math.abs (this.safeFloat (order, 7)); - const filled = amount - remaining; - const side = (order[7] < 0) ? 'sell' : 'buy'; + const remaining = Math.abs (this.safeNumber (order, 6)); + const signedAmount = this.safeNumber (order, 7); + const amount = Math.abs (signedAmount); + const side = (signedAmount < 0) ? 'sell' : 'buy'; const orderType = this.safeString (order, 8); const type = this.safeString (this.safeValue (this.options, 'exchangeTypes'), orderType); let status = undefined; @@ -916,11 +1008,10 @@ module.exports = class bitfinex2 extends bitfinex { const parts = statusString.split (' @ '); status = this.parseOrderStatus (this.safeString (parts, 0)); } - const price = this.safeFloat (order, 16); - const average = this.safeFloat (order, 17); - const cost = price * filled; + const price = this.safeNumber (order, 16); + const average = this.safeNumber (order, 17); const clientOrderId = this.safeString (order, 2); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -935,14 +1026,14 @@ module.exports = class bitfinex2 extends bitfinex { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -959,11 +1050,11 @@ module.exports = class bitfinex2 extends bitfinex { if ((orderType === 'LIMIT') || (orderType === 'EXCHANGE LIMIT')) { request['price'] = this.numberToString (price); } else if ((orderType === 'STOP') || (orderType === 'EXCHANGE STOP')) { - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'STOP LIMIT') || (orderType === 'EXCHANGE STOP LIMIT')) { - const priceAuxLimit = this.safeFloat (params, 'price_aux_limit'); - let stopPrice = this.safeFloat (params, 'stopPrice'); + const priceAuxLimit = this.safeNumber (params, 'price_aux_limit'); + let stopPrice = this.safeNumber (params, 'stopPrice'); if (priceAuxLimit === undefined) { if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter or a price_aux_limit parameter for a ' + orderType + ' order'); @@ -978,9 +1069,9 @@ module.exports = class bitfinex2 extends bitfinex { } request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'TRAILING STOP') || (orderType === 'EXCHANGE TRAILING STOP')) { - const priceTrailing = this.safeFloat (params, 'price_trailing'); + const priceTrailing = this.safeNumber (params, 'price_trailing'); request['price_trailing'] = this.numberToString (priceTrailing); - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'FOK') || (orderType === 'EXCHANGE FOK') || (orderType === 'IOC') || (orderType === 'EXCHANGE IOC')) { request['price'] = this.numberToString (price); @@ -1312,11 +1403,11 @@ module.exports = class bitfinex2 extends bitfinex { if (currency !== undefined) { code = currency['code']; } - feeCost = this.safeFloat (data, 8); + feeCost = this.safeNumber (data, 8); if (feeCost !== undefined) { feeCost = -feeCost; } - amount = this.safeFloat (data, 5); + amount = this.safeNumber (data, 5); id = this.safeValue (data, 0); status = 'ok'; if (id === 0) { @@ -1330,7 +1421,7 @@ module.exports = class bitfinex2 extends bitfinex { timestamp = this.safeInteger (transaction, 5); updated = this.safeInteger (transaction, 6); status = this.parseTransactionStatus (this.safeString (transaction, 9)); - amount = this.safeFloat (transaction, 12); + amount = this.safeNumber (transaction, 12); if (amount !== undefined) { if (amount < 0) { type = 'withdrawal'; @@ -1338,7 +1429,7 @@ module.exports = class bitfinex2 extends bitfinex { type = 'deposit'; } } - feeCost = this.safeFloat (transaction, 13); + feeCost = this.safeNumber (transaction, 13); if (feeCost !== undefined) { feeCost = -feeCost; } @@ -1466,7 +1557,7 @@ module.exports = class bitfinex2 extends bitfinex { }); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitflyer.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitflyer.js index f9c19b59a..911cb61f0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitflyer.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitflyer.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -185,11 +186,11 @@ module.exports = class bitflyer extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'amount'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -208,16 +209,16 @@ module.exports = class bitflyer extends Exchange { }; const ticker = await this.publicGetGetticker (this.extend (request, params)); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'ltp'); + const last = this.safeNumber (ticker, 'ltp'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'best_bid'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -227,7 +228,7 @@ module.exports = class bitflyer extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_by_product'), + 'baseVolume': this.safeNumber (ticker, 'volume_by_product'), 'quoteVolume': undefined, 'info': ticker, }; @@ -251,14 +252,11 @@ module.exports = class bitflyer extends Exchange { order = this.safeString (trade, 'child_order_acceptance_id'); } const timestamp = this.parse8601 (this.safeString (trade, 'exec_date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -334,18 +332,17 @@ module.exports = class bitflyer extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'child_order_date')); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'outstanding_size'); - const filled = this.safeFloat (order, 'executed_size'); - const price = this.safeFloat (order, 'price'); - const cost = price * filled; + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'outstanding_size'); + const filled = this.safeNumber (order, 'executed_size'); + const price = this.safeNumber (order, 'price'); const status = this.parseOrderStatus (this.safeString (order, 'child_order_state')); const type = this.safeStringLower (order, 'child_order_type'); const side = this.safeStringLower (order, 'side'); const marketId = this.safeString (order, 'product_code'); const symbol = this.safeSymbol (marketId, market); let fee = undefined; - const feeCost = this.safeFloat (order, 'total_commission'); + const feeCost = this.safeNumber (order, 'total_commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -354,7 +351,7 @@ module.exports = class bitflyer extends Exchange { }; } const id = this.safeString (order, 'child_order_acceptance_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -369,14 +366,14 @@ module.exports = class bitflyer extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) { @@ -439,7 +436,7 @@ module.exports = class bitflyer extends Exchange { return this.parseTrades (response, market, since, limit); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { if (symbols === undefined) { throw new ArgumentsRequired (this.id + ' fetchPositions() requires a `symbols` argument, exactly one symbol in an array'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitforex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitforex.js index 8fa337979..0dfebbef7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitforex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitforex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, OrderNotFound, InsufficientFunds, DDoSProtection, PermissionDenied, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -259,7 +260,7 @@ module.exports = class bitforex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -295,14 +296,11 @@ module.exports = class bitforex extends Exchange { const timestamp = this.safeInteger (trade, 'time'); const id = this.safeString (trade, 'tid'); const orderId = undefined; - const amount = this.safeFloat (trade, 'amount'); - const price = this.safeFloat (trade, 'price'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const sideId = this.safeInteger (trade, 'direction'); const side = this.parseSide (sideId); return { @@ -345,12 +343,12 @@ module.exports = class bitforex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'active'); - account['total'] = this.safeFloat (balance, 'fix'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'active'); + account['total'] = this.safeString (balance, 'fix'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTicker (symbol, params = {}) { @@ -366,21 +364,21 @@ module.exports = class bitforex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (data, 'high'), - 'low': this.safeFloat (data, 'low'), - 'bid': this.safeFloat (data, 'buy'), + 'high': this.safeNumber (data, 'high'), + 'low': this.safeNumber (data, 'low'), + 'bid': this.safeNumber (data, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (data, 'sell'), + 'ask': this.safeNumber (data, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (data, 'last'), - 'last': this.safeFloat (data, 'last'), + 'close': this.safeNumber (data, 'last'), + 'last': this.safeNumber (data, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (data, 'vol'), + 'baseVolume': this.safeNumber (data, 'vol'), 'quoteVolume': undefined, 'info': response, }; @@ -400,11 +398,11 @@ module.exports = class bitforex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -472,26 +470,24 @@ module.exports = class bitforex extends Exchange { parseOrder (order, market = undefined) { const id = this.safeString (order, 'orderId'); - const timestamp = this.safeFloat (order, 'createTime'); - const lastTradeTimestamp = this.safeFloat (order, 'lastTime'); + const timestamp = this.safeNumber (order, 'createTime'); + const lastTradeTimestamp = this.safeNumber (order, 'lastTime'); const symbol = market['symbol']; const sideId = this.safeInteger (order, 'tradeType'); const side = this.parseSide (sideId); const type = undefined; - const price = this.safeFloat (order, 'orderPrice'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderAmount'); - const filled = this.safeFloat (order, 'dealAmount'); - const remaining = amount - filled; + const price = this.safeNumber (order, 'orderPrice'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderAmount'); + const filled = this.safeNumber (order, 'dealAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderState')); - const cost = filled * price; const feeSide = (side === 'buy') ? 'base' : 'quote'; const feeCurrency = market[feeSide]; const fee = { - 'cost': this.safeFloat (order, 'tradeFee'), + 'cost': this.safeNumber (order, 'tradeFee'), 'currency': feeCurrency, }; - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -505,16 +501,15 @@ module.exports = class bitforex extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitget.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitget.js index 3c9581955..75e458fe0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitget.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitget.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -793,7 +794,7 @@ module.exports = class bitget extends Exchange { let swap = false; const baseId = this.safeString2 (market, 'base_currency', 'coin'); const quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { marketType = 'swap'; spot = false; @@ -811,7 +812,7 @@ module.exports = class bitget extends Exchange { 'amount': parseFloat ('1e-' + sizeIncrement), 'price': parseFloat ('1e-' + tickSize), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const status = this.safeString (market, 'status'); let active = undefined; if (status !== undefined) { @@ -1068,26 +1069,26 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat2 (ticker, 'last', 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'last', 'close'); + const open = this.safeNumber (ticker, 'open'); let bidVolume = undefined; let askVolume = undefined; let bid = this.safeValue (ticker, 'bid'); if (bid === undefined) { - bid = this.safeFloat (ticker, 'best_bid'); + bid = this.safeNumber (ticker, 'best_bid'); } else { - bidVolume = this.safeFloat (bid, 1); - bid = this.safeFloat (bid, 0); + bidVolume = this.safeNumber (bid, 1); + bid = this.safeNumber (bid, 0); } let ask = this.safeValue (ticker, 'ask'); if (ask === undefined) { - ask = this.safeFloat (ticker, 'best_ask'); + ask = this.safeNumber (ticker, 'best_ask'); } else { - askVolume = this.safeFloat (ask, 1); - ask = this.safeFloat (ask, 0); + askVolume = this.safeNumber (ask, 1); + ask = this.safeNumber (ask, 0); } - const baseVolume = this.safeFloat2 (ticker, 'amount', 'volume_24h'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber2 (ticker, 'amount', 'volume_24h'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; @@ -1101,8 +1102,8 @@ module.exports = class bitget extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -1337,9 +1338,12 @@ module.exports = class bitget extends Exchange { } let timestamp = this.safeInteger (trade, 'created_at'); timestamp = this.safeInteger2 (trade, 'timestamp', 'ts', timestamp); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'filled_amount', 'order_qty'); - amount = this.safeFloat2 (trade, 'size', 'amount', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'filled_amount', 'order_qty'); + amountString = this.safeString2 (trade, 'size', 'amount', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -1358,18 +1362,13 @@ module.exports = class bitget extends Exchange { type = this.parseOrderType (side); side = this.parseOrderSide (side); } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - let feeCost = this.safeFloat (trade, 'fee'); - if (feeCost === undefined) { - feeCost = this.safeFloat (trade, 'filled_fees'); + let feeCostString = this.safeString (trade, 'fee'); + if (feeCostString === undefined) { + feeCostString = this.safeString (trade, 'filled_fees'); } else { - feeCost = -feeCost; + feeCostString = (feeCostString[0] === '-') ? feeCostString.slice (1) : feeCostString; } + const feeCost = this.parseNumber (feeCostString); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -1492,23 +1491,23 @@ module.exports = class bitget extends Exchange { const volumeIndex = this.safeString (volume, market['type'], 'amount'); return [ this.safeInteger (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets ]; } else { const volumeIndex = this.safeValue (volume, market['type'], 6); return [ this.safeInteger (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, volumeIndex), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, volumeIndex), // Base Volume ]; } } @@ -1610,13 +1609,13 @@ module.exports = class bitget extends Exchange { } const type = this.safeValue (balance, 'type'); if (type === 'trade') { - result[code]['free'] = this.safeFloat (balance, 'balance'); + result[code]['free'] = this.safeString (balance, 'balance'); } else if ((type === 'frozen') || (type === 'lock')) { - const used = this.safeFloat (result[code], 'used'); - result[code]['used'] = this.sum (used, this.safeFloat (balance, 'balance')); + const used = this.safeString (result[code], 'used'); + result[code]['used'] = Precise.stringAdd (used, this.safeString (balance, 'balance')); } } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseSwapBalance (response) { @@ -1640,11 +1639,11 @@ module.exports = class bitget extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeString (balance, 'equity'); + account['free'] = this.safeString (balance, 'total_avail_balance'); result[symbol] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchAccounts (params = {}) { @@ -1921,26 +1920,13 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let amount = this.safeFloat2 (order, 'amount', 'size'); - const filled = this.safeFloat2 (order, 'filled_amount', 'filled_qty'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - amount = Math.max (amount, filled); - remaining = Math.max (0, amount - filled); - } - } - if (type === 'market') { - remaining = 0; - } - const cost = this.safeFloat (order, 'filled_cash_amount'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); - if ((average === undefined) && (filled !== undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } + const amount = this.safeNumber2 (order, 'amount', 'size'); + const filled = this.safeNumber2 (order, 'filled_amount', 'filled_qty'); + const cost = this.safeNumber (order, 'filled_cash_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'price_avg'); const status = this.parseOrderStatus (this.safeString2 (order, 'state', 'status')); - const feeCost = this.safeFloat2 (order, 'filled_fees', 'fee'); + const feeCost = this.safeNumber2 (order, 'filled_fees', 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -1950,7 +1936,7 @@ module.exports = class bitget extends Exchange { }; } const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1968,11 +1954,11 @@ module.exports = class bitget extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -2019,7 +2005,7 @@ module.exports = class bitget extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'amount'); + let cost = this.safeNumber (params, 'amount'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2569,12 +2555,12 @@ module.exports = class bitget extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const txid = this.safeString (transaction, 'tx_hash'); const timestamp = this.safeInteger (transaction, 'created_at'); const updated = this.safeInteger (transaction, 'updated_at'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -2764,7 +2750,7 @@ module.exports = class bitget extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.swapGetPositionAllPosition (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bithumb.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bithumb.js index ef4e7d479..051562718 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bithumb.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bithumb.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); const { DECIMAL_PLACES, SIGNIFICANT_DIGITS, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -198,12 +199,12 @@ module.exports = class bithumb extends Exchange { const account = this.account (); const currency = this.currency (code); const lowerCurrencyId = this.safeStringLower (currency, 'id'); - account['total'] = this.safeFloat (balances, 'total_' + lowerCurrencyId); - account['used'] = this.safeFloat (balances, 'in_use_' + lowerCurrencyId); - account['free'] = this.safeFloat (balances, 'available_' + lowerCurrencyId); + account['total'] = this.safeString (balances, 'total_' + lowerCurrencyId); + account['used'] = this.safeString (balances, 'in_use_' + lowerCurrencyId); + account['free'] = this.safeString (balances, 'available_' + lowerCurrencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -265,8 +266,8 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'opening_price'); - const close = this.safeFloat (ticker, 'closing_price'); + const open = this.safeNumber (ticker, 'opening_price'); + const close = this.safeNumber (ticker, 'closing_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -277,18 +278,18 @@ module.exports = class bithumb extends Exchange { } average = this.sum (open, close) / 2; } - const baseVolume = this.safeFloat (ticker, 'units_traded_24H'); - const quoteVolume = this.safeFloat (ticker, 'acc_trade_value_24H'); + const baseVolume = this.safeNumber (ticker, 'units_traded_24H'); + const quoteVolume = this.safeNumber (ticker, 'acc_trade_value_24H'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -394,11 +395,11 @@ module.exports = class bithumb extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -488,18 +489,16 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'units_traded', 'units'); - let cost = this.safeFloat (trade, 'total'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'units_traded', 'units'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId); @@ -702,14 +701,14 @@ module.exports = class bithumb extends Exchange { const sideProperty = this.safeValue2 (order, 'type', 'side'); const side = (sideProperty === 'bid') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'order_status')); - let price = this.safeFloat2 (order, 'order_price', 'price'); + let price = this.safeNumber2 (order, 'order_price', 'price'); let type = 'limit'; if (price === 0) { price = undefined; type = 'market'; } - const amount = this.safeFloat2 (order, 'order_qty', 'units'); - let remaining = this.safeFloat (order, 'units_remaining'); + const amount = this.safeNumber2 (order, 'order_qty', 'units'); + let remaining = this.safeNumber (order, 'units_remaining'); if (remaining === undefined) { if (status === 'closed') { remaining = 0; @@ -728,65 +727,14 @@ module.exports = class bithumb extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let filled = undefined; - let cost = undefined; - let average = undefined; const id = this.safeString (order, 'order_id'); - const rawTrades = this.safeValue (order, 'contract'); - let trades = undefined; - let fee = undefined; - let fees = undefined; - let feesByCurrency = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'side': side, - 'symbol': symbol, - 'order': id, - }); - filled = 0; - feesByCurrency = {}; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - filled = this.sum (filled, trade['amount']); - cost = this.sum (cost, trade['cost']); - const tradeFee = trade['fee']; - const feeCurrency = tradeFee['currency']; - if (feeCurrency in feesByCurrency) { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': this.sum (feesByCurrency[feeCurrency]['cost'], tradeFee['cost']), - }; - } else { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': tradeFee['cost'], - }; - } - } - const feeCurrencies = Object.keys (feesByCurrency); - const feeCurrenciesLength = feeCurrencies.length; - if (feeCurrenciesLength > 1) { - fees = []; - for (let i = 0; i < feeCurrencies.length; i++) { - const feeCurrency = feeCurrencies[i]; - fees.push (feesByCurrency[feeCurrency]); - } - } else { - fee = this.safeValue (feesByCurrency, feeCurrencies[0]); - } - if (filled !== 0) { - average = cost / filled; - } - } - if (amount !== undefined) { - if ((filled === undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if ((remaining === undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const result = { + const rawTrades = this.safeValue (order, 'contract', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'side': side, + 'symbol': symbol, + 'order': id, + }); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -801,20 +749,14 @@ module.exports = class bithumb extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, + 'cost': undefined, + 'average': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': trades, - }; - if (fee !== undefined) { - result['fee'] = fee; - } else if (fees !== undefined) { - result['fees'] = fees; - } - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmart.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmart.js index 4ad47118a..9ec806c6e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmart.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmart.js @@ -435,16 +435,16 @@ module.exports = class bitmart extends Exchange { // const pricePrecision = this.safeInteger (market, 'price_max_precision'); const precision = { - 'amount': this.safeFloat (market, 'base_min_size'), + 'amount': this.safeNumber (market, 'base_min_size'), 'price': parseFloat (this.decimalToPrecision (Math.pow (10, -pricePrecision), ROUND, 10)), }; - const minBuyCost = this.safeFloat (market, 'min_buy_amount'); - const minSellCost = this.safeFloat (market, 'min_sell_amount'); + const minBuyCost = this.safeNumber (market, 'min_buy_amount'); + const minSellCost = this.safeNumber (market, 'min_sell_amount'); const minCost = Math.max (minBuyCost, minSellCost); const limits = { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': { 'min': undefined, @@ -554,16 +554,16 @@ module.exports = class bitmart extends Exchange { // // the docs are wrong: https://github.com/ccxt/ccxt/issues/5612 // - const amountPrecision = this.safeFloat (contract, 'vol_unit'); - const pricePrecision = this.safeFloat (contract, 'price_unit'); + const amountPrecision = this.safeNumber (contract, 'vol_unit'); + const pricePrecision = this.safeNumber (contract, 'price_unit'); const precision = { 'amount': amountPrecision, 'price': pricePrecision, }; const limits = { 'amount': { - 'min': this.safeFloat (contract, 'min_vol'), - 'max': this.safeFloat (contract, 'max_vol'), + 'min': this.safeNumber (contract, 'min_vol'), + 'max': this.safeNumber (contract, 'max_vol'), }, 'price': { 'min': undefined, @@ -586,8 +586,8 @@ module.exports = class bitmart extends Exchange { future = true; } const feeConfig = this.safeValue (market, 'fee_config', {}); - const maker = this.safeFloat (feeConfig, 'maker_fee'); - const taker = this.safeFloat (feeConfig, 'taker_fee'); + const maker = this.safeNumber (feeConfig, 'maker_fee'); + const taker = this.safeNumber (feeConfig, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -675,33 +675,33 @@ module.exports = class bitmart extends Exchange { const timestamp = this.safeTimestamp (ticker, 'timestamp', this.milliseconds ()); const marketId = this.safeString2 (ticker, 'symbol', 'contract_id'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat2 (ticker, 'close_24h', 'last_price'); - let percentage = this.safeFloat (ticker, 'fluctuation', 'rise_fall_rate'); + const last = this.safeNumber2 (ticker, 'close_24h', 'last_price'); + let percentage = this.safeNumber (ticker, 'fluctuation', 'rise_fall_rate'); if (percentage !== undefined) { percentage *= 100; } - const baseVolume = this.safeFloat2 (ticker, 'base_volume_24h', 'base_coin_volume'); - const quoteVolume = this.safeFloat2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); + const baseVolume = this.safeNumber2 (ticker, 'base_volume_24h', 'base_coin_volume'); + const quoteVolume = this.safeNumber2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const open = this.safeFloat2 (ticker, 'open_24h', 'open'); + const open = this.safeNumber2 (ticker, 'open_24h', 'open'); let average = undefined; if ((last !== undefined) && (open !== undefined)) { average = this.sum (last, open) / 2; } - average = this.safeFloat (ticker, 'avg_price', average); + average = this.safeNumber (ticker, 'avg_price', average); const price = this.safeValue (ticker, 'depth_price', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), - 'bid': this.safeFloat (price, 'best_bid', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (price, 'best_ask', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), + 'bid': this.safeNumber (price, 'best_bid', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (price, 'best_ask', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open_24h'), + 'open': this.safeNumber (ticker, 'open_24h'), 'close': last, 'last': last, 'previousClose': undefined, @@ -1005,18 +1005,18 @@ module.exports = class bitmart extends Exchange { if (execType !== undefined) { takerOrMaker = (execType === 'M') ? 'maker' : 'taker'; } - let price = this.safeFloat2 (trade, 'price', 'deal_price'); - price = this.safeFloat (trade, 'price_avg', price); - let amount = this.safeFloat2 (trade, 'amount', 'deal_vol'); - amount = this.safeFloat (trade, 'size', amount); - let cost = this.safeFloat2 (trade, 'count', 'notional'); + let price = this.safeNumber2 (trade, 'price', 'deal_price'); + price = this.safeNumber (trade, 'price_avg', price); + let amount = this.safeNumber2 (trade, 'amount', 'deal_vol'); + amount = this.safeNumber (trade, 'size', amount); + let cost = this.safeNumber2 (trade, 'count', 'notional'); if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { cost = amount * price; } const orderId = this.safeInteger (trade, 'order_id'); const marketId = this.safeString2 (trade, 'contract_id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (trade, 'fees'); + const feeCost = this.safeNumber (trade, 'fees'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_coin_name'); @@ -1144,11 +1144,11 @@ module.exports = class bitmart extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1475,11 +1475,11 @@ module.exports = class bitmart extends Exchange { currencyId = this.safeString (balance, 'coind_code', currencyId); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat2 (balance, 'available', 'available_vol'); - account['used'] = this.safeFloat2 (balance, 'frozen', 'freeze_vol'); + account['free'] = this.safeString2 (balance, 'available', 'available_vol'); + account['used'] = this.safeString2 (balance, 'frozen', 'freeze_vol'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -1548,29 +1548,10 @@ module.exports = class bitmart extends Exchange { if (market !== undefined) { status = this.parseOrderStatusByType (market['type'], this.safeString (order, 'status')); } - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat2 (order, 'price_avg', 'done_avg_price'); - const amount = this.safeFloat2 (order, 'size', 'vol'); - let cost = undefined; - let filled = this.safeFloat2 (order, 'filled_size', 'done_vol'); - let remaining = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - if (filled === undefined) { - filled = Math.max (0, amount - remaining); - } - } - if (filled !== undefined) { - if (remaining === undefined) { - remaining = Math.max (0, amount - filled); - } - if (cost === undefined) { - if (average !== undefined) { - cost = average * filled; - } - } - } - } + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber2 (order, 'price_avg', 'done_avg_price'); + const amount = this.safeNumber2 (order, 'size', 'vol'); + const filled = this.safeNumber2 (order, 'filled_size', 'done_vol'); let side = this.safeString (order, 'side'); // 1 = Open long // 2 = Close short @@ -1592,7 +1573,7 @@ module.exports = class bitmart extends Exchange { average = undefined; } } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -1607,14 +1588,14 @@ module.exports = class bitmart extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatusByType (type, status) { @@ -1655,7 +1636,7 @@ module.exports = class bitmart extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2241,12 +2222,12 @@ module.exports = class bitmart extends Exchange { type = 'deposit'; id = depositId; } - const amount = this.safeFloat (transaction, 'arrival_amount'); + const amount = this.safeNumber (transaction, 'arrival_amount'); const timestamp = this.safeInteger (transaction, 'tapply_timeime'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmex.js index 4f5a0552a..8eddc8287 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, BadRequest, DDoSProtection, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -215,8 +216,8 @@ module.exports = class bitmex extends Exchange { 'amount': undefined, 'price': undefined, }; - const lotSize = this.safeFloat (market, 'lotSize'); - const tickSize = this.safeFloat (market, 'tickSize'); + const lotSize = this.safeNumber (market, 'lotSize'); + const tickSize = this.safeNumber (market, 'tickSize'); if (lotSize !== undefined) { precision['amount'] = lotSize; } @@ -230,7 +231,7 @@ module.exports = class bitmex extends Exchange { }, 'price': { 'min': tickSize, - 'max': this.safeFloat (market, 'maxPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { 'min': undefined, @@ -240,7 +241,7 @@ module.exports = class bitmex extends Exchange { const limitField = (position === quote) ? 'cost' : 'amount'; limits[limitField] = { 'min': lotSize, - 'max': this.safeFloat (market, 'maxOrderQty'), + 'max': this.safeNumber (market, 'maxOrderQty'), }; result.push ({ 'id': id, @@ -252,8 +253,8 @@ module.exports = class bitmex extends Exchange { 'active': active, 'precision': precision, 'limits': limits, - 'taker': this.safeFloat (market, 'takerFee'), - 'maker': this.safeFloat (market, 'makerFee'), + 'taker': this.safeNumber (market, 'takerFee'), + 'maker': this.safeNumber (market, 'makerFee'), 'type': type, 'spot': false, 'swap': swap, @@ -319,21 +320,17 @@ module.exports = class bitmex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - let free = this.safeFloat (balance, 'availableMargin'); - let total = this.safeFloat (balance, 'marginBalance'); + let free = this.safeString (balance, 'availableMargin'); + let total = this.safeString (balance, 'marginBalance'); if (code === 'BTC') { - if (free !== undefined) { - free /= 100000000; - } - if (total !== undefined) { - total /= 100000000; - } + free = Precise.stringDiv (free, '1e8'); + total = Precise.stringDiv (total, '1e8'); } account['free'] = free; account['total'] = total; result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -412,8 +409,8 @@ module.exports = class bitmex extends Exchange { for (let i = 0; i < response.length; i++) { const order = response[i]; const side = (order['side'] === 'Sell') ? 'asks' : 'bids'; - const amount = this.safeFloat (order, 'size'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const price = this.safeNumber (order, 'price'); // https://github.com/ccxt/ccxt/issues/4926 // https://github.com/ccxt/ccxt/issues/4927 // the exchange sometimes returns null price in the orderbook @@ -619,7 +616,7 @@ module.exports = class bitmex extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'transactType')); const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount !== undefined) { amount = amount / 100000000; } @@ -630,7 +627,7 @@ module.exports = class bitmex extends Exchange { // for unrealized pnl and other transactions without a timestamp timestamp = 0; // see comments above } - let feeCost = this.safeFloat (item, 'fee', 0); + let feeCost = this.safeNumber (item, 'fee', 0); if (feeCost !== undefined) { feeCost = feeCost / 100000000; } @@ -638,7 +635,7 @@ module.exports = class bitmex extends Exchange { 'cost': feeCost, 'currency': code, }; - let after = this.safeFloat (item, 'walletBalance'); + let after = this.safeNumber (item, 'walletBalance'); if (after !== undefined) { after = after / 100000000; } @@ -957,8 +954,8 @@ module.exports = class bitmex extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const open = this.safeFloat (ticker, 'prevPrice24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'prevPrice24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; if (last !== undefined && open !== undefined) { @@ -971,13 +968,13 @@ module.exports = class bitmex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askPrice'), + 'ask': this.safeNumber (ticker, 'askPrice'), 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'vwap'), + 'vwap': this.safeNumber (ticker, 'vwap'), 'open': open, 'close': last, 'last': last, @@ -985,8 +982,8 @@ module.exports = class bitmex extends Exchange { 'change': change, 'percentage': percentage, 'average': this.sum (open, last) / 2, - 'baseVolume': this.safeFloat (ticker, 'homeNotional24h'), - 'quoteVolume': this.safeFloat (ticker, 'foreignNotional24h'), + 'baseVolume': this.safeNumber (ticker, 'homeNotional24h'), + 'quoteVolume': this.safeNumber (ticker, 'foreignNotional24h'), 'info': ticker, }; } @@ -1011,11 +1008,11 @@ module.exports = class bitmex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1144,23 +1141,23 @@ module.exports = class bitmex extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat2 (trade, 'avgPx', 'price'); - const amount = this.safeFloat2 (trade, 'size', 'lastQty'); + const price = this.safeNumber2 (trade, 'avgPx', 'price'); + const amount = this.safeNumber2 (trade, 'size', 'lastQty'); const id = this.safeString (trade, 'trdMatchID'); const order = this.safeString (trade, 'orderID'); const side = this.safeStringLower (trade, 'side'); // price * amount doesn't work for all symbols (e.g. XBT, ETH) - let cost = this.safeFloat (trade, 'execCost'); + let cost = this.safeNumber (trade, 'execCost'); if (cost !== undefined) { cost = Math.abs (cost) / 100000000; } let fee = undefined; if ('execComm' in trade) { - let feeCost = this.safeFloat (trade, 'execComm'); + let feeCost = this.safeNumber (trade, 'execComm'); feeCost = feeCost / 100000000; const currencyId = this.safeString (trade, 'settlCurrency'); const feeCurrency = this.safeCurrencyCode (currencyId); - const feeRate = this.safeFloat (trade, 'commission'); + const feeRate = this.safeNumber (trade, 'commission'); fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -1262,33 +1259,19 @@ module.exports = class bitmex extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'transactTime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty', 0.0); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (amount - filled, 0.0); - } - } - const average = this.safeFloat (order, 'avgPx'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = average * filled; - } else if (price !== undefined) { - cost = price * filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty', 0.0); + const average = this.safeNumber (order, 'avgPx'); const id = this.safeString (order, 'orderID'); const type = this.safeStringLower (order, 'ordType'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'clOrdID'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'ParticipateDoNotInitiate'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1303,14 +1286,14 @@ module.exports = class bitmex extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { @@ -1371,7 +1354,7 @@ module.exports = class bitmex extends Exchange { 'ordType': orderType, }; if ((orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched')) { - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPx or stopPrice parameter for the ' + orderType + ' order type'); } else { @@ -1488,7 +1471,7 @@ module.exports = class bitmex extends Exchange { return this.parseOrders (response, market); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPosition (params); // [ diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitpanda.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitpanda.js index b440aba7d..5f857014b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitpanda.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitpanda.js @@ -328,7 +328,7 @@ module.exports = class bitpanda extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; @@ -401,9 +401,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -450,8 +450,8 @@ module.exports = class bitpanda extends Exchange { const activeFeeTier = this.safeValue (response, 'active_fee_tier', {}); const result = { 'info': response, - 'maker': this.safeFloat (activeFeeTier, 'maker_fee'), - 'taker': this.safeFloat (activeFeeTier, 'taker_fee'), + 'maker': this.safeNumber (activeFeeTier, 'maker_fee'), + 'taker': this.safeNumber (activeFeeTier, 'taker_fee'), 'percentage': true, 'tierBased': true, }; @@ -460,9 +460,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -500,27 +500,27 @@ module.exports = class bitpanda extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last_price'); - const percentage = this.safeFloat (ticker, 'price_change_percentage'); - const change = this.safeFloat (ticker, 'price_change'); + const last = this.safeNumber (ticker, 'last_price'); + const percentage = this.safeNumber (ticker, 'price_change_percentage'); + const change = this.safeNumber (ticker, 'price_change'); let open = undefined; let average = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'best_bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -705,11 +705,11 @@ module.exports = class bitpanda extends Exchange { const volumeField = this.safeString (options, 'volume', 'total_amount'); return [ alignedTimestamp, - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -795,21 +795,21 @@ module.exports = class bitpanda extends Exchange { timestamp = this.parse8601 (this.safeString (trade, 'time')); } const side = this.safeStringLower2 (trade, 'side', 'taker_side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + let cost = this.safeNumber (trade, 'volume'); if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { cost = amount * price; } const marketId = this.safeString (trade, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (feeInfo, 'fee_amount'); + const feeCost = this.safeNumber (feeInfo, 'fee_amount'); let takerOrMaker = undefined; let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (feeInfo, 'fee_percentage'); + const feeRate = this.safeNumber (feeInfo, 'fee_percentage'); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, @@ -892,11 +892,11 @@ module.exports = class bitpanda extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -1150,12 +1150,12 @@ module.exports = class bitpanda extends Exchange { // } // const id = this.safeString (transaction, 'transaction_id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const currencyId = this.safeString (transaction, 'currency'); currency = this.safeCurrency (currencyId, currency); const status = 'ok'; // the exchange returns cleared transactions only - const feeCost = this.safeFloat2 (transaction, 'fee_amount', 'fee'); + const feeCost = this.safeNumber2 (transaction, 'fee_amount', 'fee'); let fee = undefined; const addressTo = this.safeString (transaction, 'recipient'); const tagTo = this.safeString (transaction, 'destination_tag'); @@ -1270,72 +1270,34 @@ module.exports = class bitpanda extends Exchange { // ] // } // - const rawTrades = this.safeValue (order, 'trades', []); - order = this.safeValue (order, 'order', order); - const id = this.safeString (order, 'order_id'); - const clientOrderId = this.safeString (order, 'client_id'); - const timestamp = this.parse8601 (this.safeString (order, 'time')); - let status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'instrument_code'); + const rawOrder = this.safeValue (order, 'order', order); + const id = this.safeString (rawOrder, 'order_id'); + const clientOrderId = this.safeString (rawOrder, 'client_id'); + const timestamp = this.parse8601 (this.safeString (rawOrder, 'time')); + const rawStatus = this.parseOrderStatus (this.safeString (rawOrder, 'status')); + const status = this.parseOrderStatus (rawStatus); + const marketId = this.safeString (rawOrder, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - if (status === undefined) { - if (remaining > 0) { - status = 'open'; - } else { - status = 'closed'; - } - } - } - } - const side = this.safeStringLower (order, 'side'); - const type = this.safeStringLower (order, 'type'); - const trades = this.parseTrades (rawTrades, market, undefined, undefined); - const fees = []; - const numTrades = trades.length; - let lastTradeTimestamp = undefined; - let tradeCost = undefined; - let tradeAmount = undefined; - if (numTrades > 0) { - lastTradeTimestamp = trades[0]['timestamp']; - tradeCost = 0; - tradeAmount = 0; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - fees.push (trade['fee']); - lastTradeTimestamp = Math.max (lastTradeTimestamp, trade['timestamp']); - tradeCost = this.sum (tradeCost, trade['cost']); - tradeAmount = this.sum (tradeAmount, trade['amount']); - } - } - let average = this.safeFloat (order, 'average_price'); - if (average === undefined) { - if ((tradeCost !== undefined) && (tradeAmount !== undefined) && (tradeAmount !== 0)) { - average = tradeCost / tradeAmount; - } - } - if (cost === undefined) { - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - } - const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'trigger_price'); - const postOnly = this.safeValue (order, 'is_post_only'); - const result = { + const price = this.safeNumber (rawOrder, 'price'); + const amount = this.safeNumber (rawOrder, 'amount'); + const filledString = this.safeString (rawOrder, 'filled_amount'); + const filled = this.parseNumber (filledString); + const side = this.safeStringLower (rawOrder, 'side'); + const type = this.safeStringLower (rawOrder, 'type'); + const timeInForce = this.parseTimeInForce (this.safeString (rawOrder, 'time_in_force')); + const stopPrice = this.safeNumber (rawOrder, 'trigger_price'); + const postOnly = this.safeValue (rawOrder, 'is_post_only'); + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'type': type, + }); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -1344,41 +1306,14 @@ module.exports = class bitpanda extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, // 'fee': undefined, 'trades': trades, - }; - const numFees = fees.length; - if (numFees > 0) { - if (numFees === 1) { - result['fee'] = fees[0]; - } else { - const feesByCurrency = this.groupBy (fees, 'currency'); - const feeCurrencies = Object.keys (feesByCurrency); - const numFeesByCurrency = feeCurrencies.length; - if (numFeesByCurrency === 1) { - const feeCurrency = feeCurrencies[0]; - const feeArray = this.safeValue (feesByCurrency, feeCurrency); - let feeCost = 0; - for (let i = 0; i < feeArray.length; i++) { - feeCost = this.sum (feeCost, feeArray[i]['cost']); - } - result['fee'] = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } else { - result['fees'] = fees; - } - } - } else { - result['fee'] = undefined; - } - return result; + }); } parseTimeInForce (timeInForce) { @@ -1412,7 +1347,7 @@ module.exports = class bitpanda extends Exchange { priceIsRequired = true; } if (uppercaseType === 'STOP') { - const triggerPrice = this.safeFloat (params, 'trigger_price'); + const triggerPrice = this.safeNumber (params, 'trigger_price'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a trigger_price param for ' + type + ' orders'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitso.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitso.js index d8bc07145..defcece54 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitso.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitso.js @@ -157,28 +157,28 @@ module.exports = class bitso extends Exchange { const symbol = base + '/' + quote; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), - 'max': this.safeFloat (market, 'maximum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), + 'max': this.safeNumber (market, 'maximum_amount'), }, 'price': { - 'min': this.safeFloat (market, 'minimum_price'), - 'max': this.safeFloat (market, 'maximum_price'), + 'min': this.safeNumber (market, 'minimum_price'), + 'max': this.safeNumber (market, 'maximum_price'), }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), - 'max': this.safeFloat (market, 'maximum_value'), + 'min': this.safeNumber (market, 'minimum_value'), + 'max': this.safeNumber (market, 'maximum_value'), }, }; - const defaultPricePrecision = this.safeFloat (this.options['precision'], quote, this.options['defaultPrecision']); - const pricePrecision = this.safeFloat (market, 'tick_size', defaultPricePrecision); + const defaultPricePrecision = this.safeNumber (this.options['precision'], quote, this.options['defaultPrecision']); + const pricePrecision = this.safeNumber (market, 'tick_size', defaultPricePrecision); const precision = { - 'amount': this.safeFloat (this.options['precision'], base, this.options['defaultPrecision']), + 'amount': this.safeNumber (this.options['precision'], base, this.options['defaultPrecision']), 'price': pricePrecision, }; const fees = this.safeValue (market, 'fees', {}); const flatRate = this.safeValue (fees, 'flat_rate', {}); - const maker = this.safeFloat (flatRate, 'maker'); - const taker = this.safeFloat (flatRate, 'taker'); + const maker = this.safeNumber (flatRate, 'maker'); + const taker = this.safeNumber (flatRate, 'taker'); const feeTiers = this.safeValue (fees, 'structure', []); const fee = { 'taker': parseFloat (this.decimalToPrecision (taker / 100, ROUND, 0.00000001, TICK_SIZE)), @@ -190,9 +190,9 @@ module.exports = class bitso extends Exchange { const makerFees = []; for (let j = 0; j < feeTiers.length; j++) { const tier = feeTiers[j]; - const volume = this.safeFloat (tier, 'volume'); - const takerFee = this.safeFloat (tier, 'taker'); - const makerFee = this.safeFloat (tier, 'maker'); + const volume = this.safeNumber (tier, 'volume'); + const takerFee = this.safeNumber (tier, 'taker'); + const makerFee = this.safeNumber (tier, 'maker'); const takerFeeToPrecision = parseFloat (this.decimalToPrecision (takerFee / 100, ROUND, 0.00000001, TICK_SIZE)); const makerFeeToPrecision = parseFloat (this.decimalToPrecision (makerFee / 100, ROUND, 0.00000001, TICK_SIZE)); takerFees.push ([ volume, takerFeeToPrecision ]); @@ -232,14 +232,13 @@ module.exports = class bitso extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'locked'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -261,22 +260,22 @@ module.exports = class bitso extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'payload'); const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -297,12 +296,12 @@ module.exports = class bitso extends Exchange { const marketId = this.safeString (trade, 'book'); const symbol = this.safeSymbol (marketId, market, '_'); const side = this.safeString2 (trade, 'side', 'maker_side'); - let amount = this.safeFloat2 (trade, 'amount', 'major'); + let amount = this.safeNumber2 (trade, 'amount', 'major'); if (amount !== undefined) { amount = Math.abs (amount); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fees_amount'); + const feeCost = this.safeNumber (trade, 'fees_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fees_currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -311,11 +310,11 @@ module.exports = class bitso extends Exchange { 'currency': feeCurrency, }; } - let cost = this.safeFloat (trade, 'minor'); + let cost = this.safeNumber (trade, 'minor'); if (cost !== undefined) { cost = Math.abs (cost); } - const price = this.safeFloat (trade, 'price'); + const price = this.safeNumber (trade, 'price'); const orderId = this.safeString (trade, 'oid'); const id = this.safeString (trade, 'tid'); return { @@ -416,17 +415,11 @@ module.exports = class bitso extends Exchange { const symbol = this.safeSymbol (marketId, market, '_'); const orderType = this.safeString (order, 'type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'unfilled_amount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'unfilled_amount'); const clientOrderId = this.safeString (order, 'client_id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -443,12 +436,12 @@ module.exports = class bitso extends Exchange { 'amount': amount, 'cost': undefined, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = 25, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp.js index 4671385bf..0ac6fe9f7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp.js @@ -115,6 +115,16 @@ module.exports = class bitstamp extends Exchange { 'usdc_address/', 'omg_withdrawal/', 'omg_address/', + 'dai_withdrawal/', + 'dai_address/', + 'knc_withdrawal/', + 'knc_address/', + 'mkr_withdrawal/', + 'mkr_address/', + 'zrx_withdrawal/', + 'zrx_address/', + 'gusd_withdrawal/', + 'gusd_address/', 'transfer-to-main/', 'transfer-from-main/', 'withdrawal-requests/', @@ -249,13 +259,15 @@ module.exports = class bitstamp extends Exchange { const symbolId = baseId + '_' + quoteId; const id = this.safeString (market, 'url_symbol'); const precision = { - 'amount': market['base_decimals'], - 'price': market['counter_decimals'], + 'amount': this.safeInteger (market, 'base_decimals'), + 'price': this.safeInteger (market, 'counter_decimals'), }; - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; // let [ cost, currency ] = market['minimum_order'].split (' '); - const active = (market['trading'] === 'Enabled'); + const trading = this.safeString (market, 'trading'); + const active = (trading === 'Enabled'); result.push ({ 'id': id, 'symbol': symbol, @@ -299,7 +311,7 @@ module.exports = class bitstamp extends Exchange { 'type': currencyType, 'name': name, 'active': true, - 'fee': this.safeFloat (description['fees']['funding']['withdraw'], code), + 'fee': this.safeNumber (description['fees']['funding']['withdraw'], code), 'precision': precision, 'limits': { 'amount': { @@ -352,13 +364,16 @@ module.exports = class bitstamp extends Exchange { quote = this.safeCurrencyCode (quote); const description = this.safeString (market, 'description'); const [ baseDescription, quoteDescription ] = description.split (' / '); - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; if (!(base in result)) { - result[base] = this.constructCurrencyObject (baseId, base, baseDescription, market['base_decimals'], undefined, market); + const baseDecimals = this.safeInteger (market, 'base_decimals'); + result[base] = this.constructCurrencyObject (baseId, base, baseDescription, baseDecimals, undefined, market); } if (!(quote in result)) { - result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, market['counter_decimals'], parseFloat (cost), market); + const counterDecimals = this.safeInteger (market, 'counter_decimals'); + result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, counterDecimals, parseFloat (cost), market); } } return result; @@ -400,25 +415,25 @@ module.exports = class bitstamp extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -461,7 +476,7 @@ module.exports = class bitstamp extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; if (id.indexOf ('_') < 0) { - const value = this.safeFloat (transaction, id); + const value = this.safeNumber (transaction, id); if ((value !== undefined) && (value !== 0)) { return id; } @@ -543,11 +558,11 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString2 (trade, 'id', 'tid'); let symbol = undefined; let side = undefined; - let price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat (trade, 'amount'); + let price = this.safeNumber (trade, 'price'); + let amount = this.safeNumber (trade, 'amount'); const orderId = this.safeString (trade, 'order_id'); const type = undefined; - let cost = this.safeFloat (trade, 'cost'); + let cost = this.safeNumber (trade, 'cost'); if (market === undefined) { const keys = Object.keys (trade); for (let i = 0; i < keys.length; i++) { @@ -564,12 +579,12 @@ module.exports = class bitstamp extends Exchange { market = this.getMarketFromTrade (trade); } } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = undefined; if (market !== undefined) { - price = this.safeFloat (trade, market['symbolId'], price); - amount = this.safeFloat (trade, market['baseId'], amount); - cost = this.safeFloat (trade, market['quoteId'], cost); + price = this.safeNumber (trade, market['symbolId'], price); + amount = this.safeNumber (trade, market['baseId'], amount); + cost = this.safeNumber (trade, market['quoteId'], cost); feeCurrency = market['quote']; symbol = market['symbol']; } @@ -638,7 +653,7 @@ module.exports = class bitstamp extends Exchange { parseTradingFee (balances, symbol) { const market = this.market (symbol); - const tradeFee = this.safeFloat (balances, market['id'] + '_fee'); + const tradeFee = this.safeNumber (balances, market['id'] + '_fee'); return { 'symbol': symbol, 'maker': tradeFee, @@ -688,11 +703,11 @@ module.exports = class bitstamp extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -750,12 +765,12 @@ module.exports = class bitstamp extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -802,7 +817,7 @@ module.exports = class bitstamp extends Exchange { if (id.indexOf ('_withdrawal_fee') >= 0) { const currencyId = id.split ('_')[0]; const code = this.safeCurrencyCode (currencyId); - withdraw[code] = this.safeFloat (balance, id); + withdraw[code] = this.safeNumber (balance, id); } } return { @@ -1048,16 +1063,16 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString (transaction, 'id'); const currencyId = this.getCurrencyIdFromTransaction (transaction); const code = this.safeCurrencyCode (currencyId, currency); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let feeCurrency = undefined; let amount = undefined; if ('amount' in transaction) { - amount = this.safeFloat (transaction, 'amount'); + amount = this.safeNumber (transaction, 'amount'); } else if (currency !== undefined) { - amount = this.safeFloat (transaction, currency['id'], amount); + amount = this.safeNumber (transaction, currency['id'], amount); feeCurrency = currency['code']; } else if ((code !== undefined) && (currencyId !== undefined)) { - amount = this.safeFloat (transaction, currencyId, amount); + amount = this.safeNumber (transaction, currencyId, amount); feeCurrency = code; } if (amount !== undefined) { @@ -1182,83 +1197,23 @@ module.exports = class bitstamp extends Exchange { } // there is no timestamp from fetchOrder const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - let lastTradeTimestamp = undefined; - let symbol = undefined; - let marketId = this.safeStringLower (order, 'currency_pair'); - if (marketId !== undefined) { - marketId = marketId.replace ('/', ''); - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - symbol = market['symbol']; - } - } - let amount = this.safeFloat (order, 'amount'); - let filled = 0.0; - const trades = []; - const transactions = this.safeValue (order, 'transactions', []); - let feeCost = undefined; - let cost = undefined; - const numTransactions = transactions.length; - if (numTransactions > 0) { - feeCost = 0.0; - for (let i = 0; i < numTransactions; i++) { - const trade = this.parseTrade (this.extend ({ - 'order_id': id, - 'side': side, - }, transactions[i]), market); - filled = this.sum (filled, trade['amount']); - feeCost = this.sum (feeCost, trade['fee']['cost']); - if (cost === undefined) { - cost = 0.0; - } - cost = this.sum (cost, trade['cost']); - trades.push (trade); - } - lastTradeTimestamp = trades[numTransactions - 1]['timestamp']; - } + const marketId = this.safeStringLower (order, 'currency_pair'); + let symbol = this.safeSymbol (marketId, market, '/'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((status === 'closed') && (amount === undefined)) { - amount = filled; + const amount = this.safeNumber (order, 'amount'); + const transactions = this.safeValue (order, 'transactions', []); + const trades = this.parseTrades (transactions, market); + const length = trades.length; + if (length) { + symbol = trades[0]['symbol']; } - let remaining = undefined; - if (amount !== undefined) { - remaining = amount - filled; - } - let price = this.safeFloat (order, 'price'); - if (market === undefined) { - market = this.getMarketFromTrades (trades); - } - let feeCurrency = undefined; - if (market !== undefined) { - if (symbol === undefined) { - symbol = market['symbol']; - } - feeCurrency = market['quote']; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if (price === undefined) { - if (filled > 0) { - price = cost / filled; - } - } - let fee = undefined; - if (feeCost !== undefined) { - if (feeCurrency !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { + const price = this.safeNumber (order, 'price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'status': status, 'symbol': symbol, 'type': undefined, @@ -1267,15 +1222,15 @@ module.exports = class bitstamp extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, - 'filled': filled, - 'remaining': remaining, + 'filled': undefined, + 'remaining': undefined, 'trades': trades, - 'fee': fee, + 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } parseLedgerEntryType (type) { @@ -1355,11 +1310,11 @@ module.exports = class bitstamp extends Exchange { const parsedTransaction = this.parseTransaction (item); let direction = undefined; if ('amount' in item) { - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); direction = amount > 0 ? 'in' : 'out'; } else if (('currency' in parsedTransaction) && parsedTransaction['currency'] !== undefined) { const currencyId = this.currencyId (parsedTransaction['currency']); - const amount = this.safeFloat (item, currencyId); + const amount = this.safeNumber (item, currencyId); direction = amount > 0 ? 'in' : 'out'; } return { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp1.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp1.js index 8d8de5db1..2b6b70a04 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp1.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitstamp1.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -100,25 +101,25 @@ module.exports = class bitstamp1 extends Exchange { await this.loadMarkets (); const ticker = await this.publicGetTicker (params); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -141,14 +142,11 @@ module.exports = class bitstamp1 extends Exchange { } } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -192,12 +190,12 @@ module.exports = class bitstamp1 extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bittrex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bittrex.js index 1e11d600a..fb8f6fb09 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bittrex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bittrex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, DDoSProtection, PermissionDenied, AddressPending, OnMaintenance, BadRequest, InvalidAddress } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -280,7 +281,7 @@ module.exports = class bittrex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeSize'), + 'min': this.safeNumber (market, 'minTradeSize'), 'max': undefined, }, 'price': { @@ -308,11 +309,11 @@ module.exports = class bittrex extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); const balance = indexed[currencyId]; - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -372,7 +373,7 @@ module.exports = class bittrex extends Exchange { const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); const precision = 8; // default precision, todo: fix "magic constants" - const fee = this.safeFloat (currency, 'txFee'); // todo: redesign + const fee = this.safeNumber (currency, 'txFee'); // todo: redesign const isActive = this.safeString (currency, 'status'); result[code] = { 'id': id, @@ -433,17 +434,17 @@ module.exports = class bittrex extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'updatedAt')); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const percentage = this.safeFloat (ticker, 'percentChange'); - const last = this.safeFloat (ticker, 'lastTradeRate'); + const percentage = this.safeNumber (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'lastTradeRate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidRate'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidRate'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askRate'), + 'ask': this.safeNumber (ticker, 'askRate'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -453,8 +454,8 @@ module.exports = class bittrex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -567,21 +568,18 @@ module.exports = class bittrex extends Exchange { const order = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'marketSymbol'); market = this.safeMarket (marketId, market, '-'); - let cost = undefined; - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'quantity'); - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = undefined; const isTaker = this.safeValue (trade, 'isTaker'); if (isTaker !== undefined) { takerOrMaker = isTaker ? 'taker' : 'maker'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -651,11 +649,11 @@ module.exports = class bittrex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'startsAt')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -762,9 +760,9 @@ module.exports = class bittrex extends Exchange { let cost = undefined; if (isCeilingLimit) { request['limit'] = this.priceToPrecision (symbol, price); - cost = this.safeFloat2 (params, 'ceiling', 'cost', amount); + cost = this.safeNumber2 (params, 'ceiling', 'cost', amount); } else if (isCeilingMarket) { - cost = this.safeFloat2 (params, 'ceiling', 'cost'); + cost = this.safeNumber2 (params, 'ceiling', 'cost'); if (cost === undefined) { if (price === undefined) { cost = amount; @@ -923,7 +921,7 @@ module.exports = class bittrex extends Exchange { // } // const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const address = this.safeString (transaction, 'cryptoAddress'); const txid = this.safeString (transaction, 'txId'); const updated = this.parse8601 (this.safeString (transaction, 'updatedAt')); @@ -959,7 +957,7 @@ module.exports = class bittrex extends Exchange { status = 'ok'; } } - let feeCost = this.safeFloat (transaction, 'txCost'); + let feeCost = this.safeNumber (transaction, 'txCost'); if (feeCost === undefined) { if (type === 'deposit') { // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge- @@ -1016,15 +1014,9 @@ module.exports = class bittrex extends Exchange { // } // const marketSymbol = this.safeString (order, 'marketSymbol'); - let symbol = undefined; - let feeCurrency = undefined; - if (marketSymbol !== undefined) { - const [ baseId, quoteId ] = marketSymbol.split ('-'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - feeCurrency = quote; - } + market = this.safeMarket (marketSymbol, market, '-'); + const symbol = market['symbol']; + const feeCurrency = market['quote']; const direction = this.safeStringLower (order, 'direction'); const createdAt = this.safeString (order, 'createdAt'); const updatedAt = this.safeString (order, 'updatedAt'); @@ -1037,32 +1029,15 @@ module.exports = class bittrex extends Exchange { } const timestamp = this.parse8601 (createdAt); const type = this.safeStringLower (order, 'type'); - const quantity = this.safeFloat (order, 'quantity'); - const limit = this.safeFloat (order, 'limit'); - const fillQuantity = this.safeFloat (order, 'fillQuantity'); - const commission = this.safeFloat (order, 'commission'); - const proceeds = this.safeFloat (order, 'proceeds'); - let average = undefined; - let remaining = undefined; - if (fillQuantity !== undefined) { - if (proceeds !== undefined) { - if (fillQuantity > 0) { - average = proceeds / fillQuantity; - } else if (proceeds === 0) { - average = 0; - } - } - if (quantity !== undefined) { - remaining = quantity - fillQuantity; - } - } - let status = this.safeStringLower (order, 'status'); - if ((status === 'closed') && (remaining !== undefined) && (remaining > 0)) { - status = 'canceled'; - } + const quantity = this.safeNumber (order, 'quantity'); + const limit = this.safeNumber (order, 'limit'); + const fillQuantity = this.safeNumber (order, 'fillQuantity'); + const commission = this.safeNumber (order, 'commission'); + const proceeds = this.safeNumber (order, 'proceeds'); + const status = this.safeStringLower (order, 'status'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'timestamp': timestamp, @@ -1076,10 +1051,10 @@ module.exports = class bittrex extends Exchange { 'price': limit, 'stopPrice': undefined, 'cost': proceeds, - 'average': average, + 'average': undefined, 'amount': quantity, 'filled': fillQuantity, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': { 'cost': commission, @@ -1087,7 +1062,7 @@ module.exports = class bittrex extends Exchange { }, 'info': order, 'trades': undefined, - }; + }); } parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { @@ -1136,9 +1111,9 @@ module.exports = class bittrex extends Exchange { 'side': this.safeString (order, 'side'), 'order': this.safeString (order, 'id'), 'type': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'average'), - 'amount': this.safeFloat (order, 'filled'), - 'cost': this.safeFloat (order, 'cost'), + 'price': this.safeNumber (order, 'average'), + 'amount': this.safeNumber (order, 'filled'), + 'cost': this.safeNumber (order, 'cost'), 'symbol': this.safeString (order, 'symbol'), 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitvavo.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitvavo.js index e6633b568..ef66620ca 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitvavo.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitvavo.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -306,7 +307,7 @@ module.exports = class bitvavo extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minOrderInBaseAsset'), + 'min': this.safeNumber (market, 'minOrderInBaseAsset'), 'max': undefined, }, 'price': { @@ -314,7 +315,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderInQuoteAsset'), + 'min': this.safeNumber (market, 'minOrderInQuoteAsset'), 'max': undefined, }, }, @@ -377,7 +378,7 @@ module.exports = class bitvavo extends Exchange { 'code': code, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -393,7 +394,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMinAmount'), + 'min': this.safeNumber (currency, 'withdrawalMinAmount'), 'max': undefined, }, }, @@ -450,14 +451,14 @@ module.exports = class bitvavo extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); + const last = this.safeNumber (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -469,12 +470,12 @@ module.exports = class bitvavo extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': vwap, 'open': open, 'close': last, @@ -490,14 +491,6 @@ module.exports = class bitvavo extends Exchange { return result; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24h (params); @@ -611,12 +604,11 @@ module.exports = class bitvavo extends Exchange { // feeCurrency: 'EUR' // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'side'); const id = this.safeString2 (trade, 'id', 'fillId'); @@ -627,7 +619,7 @@ module.exports = class bitvavo extends Exchange { if (taker !== undefined) { takerOrMaker = taker ? 'taker' : 'maker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); @@ -698,11 +690,11 @@ module.exports = class bitvavo extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -750,13 +742,12 @@ module.exports = class bitvavo extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'inOrder'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'inOrder'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDepositAddress (code, params = {}) { @@ -806,7 +797,7 @@ module.exports = class bitvavo extends Exchange { if (price !== undefined) { cost = amount * price; } else { - cost = this.safeFloat2 (params, 'cost', 'amountQuote'); + cost = this.safeNumber2 (params, 'cost', 'amountQuote'); } if (cost !== undefined) { const precision = market['precision']['price']; @@ -819,7 +810,7 @@ module.exports = class bitvavo extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['amount'] = this.amountToPrecision (symbol, amount); } else if (isStopMarket || isStopLimit) { - let stopPrice = this.safeFloat2 (params, 'stopPrice', 'triggerAmount'); + let stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerAmount'); if (stopPrice === undefined) { if (isStopLimit) { throw new ArgumentsRequired (this.id + ' createOrder requires a stopPrice parameter for a ' + type + ' order'); @@ -881,7 +872,7 @@ module.exports = class bitvavo extends Exchange { await this.loadMarkets (); const market = this.market (symbol); let request = {}; - const amountRemaining = this.safeFloat (params, 'amountRemaining'); + const amountRemaining = this.safeNumber (params, 'amountRemaining'); params = this.omit (params, 'amountRemaining'); if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); @@ -946,7 +937,6 @@ module.exports = class bitvavo extends Exchange { throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument'); } await this.loadMarkets (); - await this.loadMarkets (); const market = this.market (symbol); const request = { 'orderId': id, @@ -1172,26 +1162,13 @@ module.exports = class bitvavo extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let remaining = this.safeFloat (order, 'amountRemaining'); - let filled = this.safeFloat (order, 'filledAmount'); - const remainingCost = this.safeFloat (order, 'remainingCost'); - if ((remainingCost !== undefined) && (remainingCost === 0.0)) { - remaining = 0; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - const cost = this.safeFloat (order, 'filledAmountQuote'); - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amountRemaining'); + const filled = this.safeNumber (order, 'filledAmount'); + const cost = this.safeNumber (order, 'filledAmountQuote'); let fee = undefined; - const feeCost = this.safeFloat (order, 'feePaid'); + const feeCost = this.safeNumber (order, 'feePaid'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1200,32 +1177,24 @@ module.exports = class bitvavo extends Exchange { 'currency': feeCurrencyCode, }; } - let lastTradeTimestamp = undefined; - const rawTrades = this.safeValue (order, 'fills'); - let trades = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'symbol': symbol, - 'order': id, - 'side': side, - }); - const numTrades = trades.length; - if (numTrades > 0) { - const lastTrade = this.safeValue (trades, numTrades - 1); - lastTradeTimestamp = lastTrade['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'symbol': symbol, + 'order': id, + 'side': side, + 'type': type, + }); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = this.safeValue (order, 'postOnly'); // https://github.com/ccxt/ccxt/issues/8489 - const stopPrice = this.safeFloat (order, 'triggerPrice'); - return { + const stopPrice = this.safeNumber (order, 'triggerPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -1235,13 +1204,13 @@ module.exports = class bitvavo extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1436,11 +1405,11 @@ module.exports = class bitvavo extends Exchange { const currencyId = this.safeString (transaction, 'symbol'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitz.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitz.js index 816bb15a4..d78900841 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitz.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitz.js @@ -59,7 +59,7 @@ module.exports = class bitz extends Exchange { 'assets': 'https://{hostname}', }, 'www': 'https://www.bitz.com', - 'doc': 'https://apidoc.bitz.com/en/', + 'doc': 'https://apidocv2.bitz.plus/en/', 'fees': 'https://www.bitz.com/fee?type=1', 'referral': 'https://u.bitz.com/register?invite_code=1429193', }, @@ -76,6 +76,11 @@ module.exports = class bitz extends Exchange { 'currencyRate', 'currencyCoinRate', 'coinRate', + 'getContractCoin', + 'getContractKline', + 'getContractOrderBook', + 'getContractTradesHistory', + 'getContractTickers', ], }, 'trade': { @@ -88,6 +93,10 @@ module.exports = class bitz extends Exchange { 'getUserNowEntrustSheet', // open orders 'getEntrustSheetInfo', // order 'depositOrWithdraw', // transactions + 'getCoinAddress', + 'getCoinAddressList', + 'marketTrade', + 'addEntrustSheetBatch', ], }, 'assets': { @@ -95,6 +104,20 @@ module.exports = class bitz extends Exchange { 'getUserAssets', ], }, + 'contract': { + 'post': [ + 'addContractTrade', + 'cancelContractTrade', + 'getContractActivePositions', + 'getContractAccountInfo', + 'getContractMyPositions', + 'getContractOrderResult', + 'getContractTradeResult', + 'getContractOrder', + 'getContractMyHistoryTrade', + 'getContractMyTrades', + ], + }, }, 'fees': { 'trading': { @@ -281,8 +304,8 @@ module.exports = class bitz extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTrade'), - 'max': this.safeFloat (market, 'maxTrade'), + 'min': this.safeNumber (market, 'minTrade'), + 'max': this.safeNumber (market, 'maxTrade'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -331,12 +354,12 @@ module.exports = class bitz extends Exchange { const currencyId = this.safeString (balance, 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lock'); - account['total'] = this.safeFloat (balance, 'num'); - account['free'] = this.safeFloat (balance, 'over'); + account['used'] = this.safeString (balance, 'lock'); + account['total'] = this.safeString (balance, 'num'); + account['free'] = this.safeString (balance, 'over'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTicker (ticker, market = undefined) { @@ -366,8 +389,8 @@ module.exports = class bitz extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'now'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'now'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -378,22 +401,22 @@ module.exports = class bitz extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': change, - 'percentage': this.safeFloat (ticker, 'priceChange24h'), + 'percentage': this.safeNumber (ticker, 'priceChange24h'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -583,8 +606,8 @@ module.exports = class bitz extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'p'); - const amount = this.safeFloat (trade, 'n'); + const price = this.safeNumber (trade, 'p'); + const amount = this.safeNumber (trade, 'n'); let cost = undefined; if (price !== undefined) { if (amount !== undefined) { @@ -652,11 +675,11 @@ module.exports = class bitz extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -754,22 +777,17 @@ module.exports = class bitz extends Exchange { if (side !== undefined) { side = (side === 'sale') ? 'sell' : 'buy'; } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'number'); - const remaining = this.safeFloat (order, 'numberOver'); - const filled = this.safeFloat (order, 'numberDeal'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'number'); + const remaining = this.safeNumber (order, 'numberOver'); + const filled = this.safeNumber (order, 'numberDeal'); let timestamp = this.safeInteger (order, 'timestamp'); if (timestamp === undefined) { timestamp = this.safeTimestamp (order, 'created'); } - let cost = this.safeFloat (order, 'orderTotalPrice'); - if (price !== undefined) { - if (filled !== undefined) { - cost = filled * price; - } - } + const cost = this.safeNumber (order, 'orderTotalPrice'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -791,7 +809,7 @@ module.exports = class bitz extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1118,7 +1136,7 @@ module.exports = class bitz extends Exchange { const type = this.safeStringLower (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'network_fee'); + const feeCost = this.safeNumber (transaction, 'network_fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1133,7 +1151,7 @@ module.exports = class bitz extends Exchange { 'address': this.safeString (transaction, 'wallet'), 'tag': this.safeString (transaction, 'memo'), 'type': type, - 'amount': this.safeFloat (transaction, 'number'), + 'amount': this.safeNumber (transaction, 'number'), 'currency': code, 'status': status, 'updated': timestamp, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bl3p.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bl3p.js index bb84442ec..832b5dc6f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bl3p.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bl3p.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -81,17 +82,19 @@ module.exports = class bl3p extends Exchange { const available = this.safeValue (wallet, 'available', {}); const balance = this.safeValue (wallet, 'balance', {}); const account = this.account (); - account['free'] = this.safeFloat (available, 'value'); - account['total'] = this.safeFloat (balance, 'value'); + account['free'] = this.safeString (available, 'value'); + account['total'] = this.safeString (balance, 'value'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { + const price = this.safeNumber (bidask, priceKey); + const size = this.safeNumber (bidask, amountKey); return [ - bidask[priceKey] / 100000.0, - bidask[amountKey] / 100000000.0, + price / 100000.0, + size / 100000000.0, ]; } @@ -111,16 +114,16 @@ module.exports = class bl3p extends Exchange { }; const ticker = await this.publicGetMarketTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -130,7 +133,7 @@ module.exports = class bl3p extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker['volume'], '24h'), + 'baseVolume': this.safeNumber (ticker['volume'], '24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -139,20 +142,13 @@ module.exports = class bl3p extends Exchange { parseTrade (trade, market = undefined) { const id = this.safeString (trade, 'trade_id'); const timestamp = this.safeInteger (trade, 'date'); - let price = this.safeFloat (trade, 'price_int'); - if (price !== undefined) { - price /= 100000.0; - } - let amount = this.safeFloat (trade, 'amount_int'); - if (amount !== undefined) { - amount /= 100000000.0; - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + let priceString = this.safeString (trade, 'price_int'); + priceString = Precise.stringDiv (priceString, '100000'); + let amountString = this.safeString (trade, 'amount_int'); + amountString = Precise.stringDiv (amountString, '100000000'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bleutrade.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bleutrade.js index 67262da33..01e7d30ce 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bleutrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bleutrade.js @@ -163,8 +163,8 @@ module.exports = class bleutrade extends Exchange { 'code': code, 'name': this.safeString (item, 'AssetLong'), 'active': this.safeValue (item, 'IsActive') && !this.safeValue (item, 'MaintenanceMode'), - 'fee': this.safeFloat (item, 'WithdrawTxFee'), - 'precision': this.safeFloat (item, 'DecimalPlaces'), + 'fee': this.safeNumber (item, 'WithdrawTxFee'), + 'precision': this.safeNumber (item, 'DecimalPlaces'), 'info': item, 'limits': this.limits, }; @@ -216,7 +216,7 @@ module.exports = class bleutrade extends Exchange { 'taker': this.fees['trading']['taker'], 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinTradeSize'), + 'min': this.safeNumber (market, 'MinTradeSize'), 'max': undefined, }, 'price': { @@ -292,8 +292,8 @@ module.exports = class bleutrade extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'TimeStamp')); const marketId = this.safeString (ticker, 'MarketName'); const symbol = this.safeSymbol (marketId, market, '_'); - const previous = this.safeFloat (ticker, 'PrevDay'); - const last = this.safeFloat (ticker, 'Last'); + const previous = this.safeNumber (ticker, 'PrevDay'); + const last = this.safeNumber (ticker, 'Last'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -308,11 +308,11 @@ module.exports = class bleutrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'High'), - 'low': this.safeFloat (ticker, 'Low'), - 'bid': this.safeFloat (ticker, 'Bid'), + 'high': this.safeNumber (ticker, 'High'), + 'low': this.safeNumber (ticker, 'Low'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': previous, @@ -322,8 +322,8 @@ module.exports = class bleutrade extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume'), - 'quoteVolume': this.safeFloat (ticker, 'BaseVolume'), + 'baseVolume': this.safeNumber (ticker, 'Volume'), + 'quoteVolume': this.safeNumber (ticker, 'BaseVolume'), 'info': ticker, }; } @@ -331,11 +331,11 @@ module.exports = class bleutrade extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (ohlcv['TimeStamp'] + '+00:00'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -411,11 +411,11 @@ module.exports = class bleutrade extends Exchange { const currencyId = this.safeString (item, 'Asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (item, 'Available'); - account['total'] = this.safeFloat (item, 'Balance'); + account['free'] = this.safeString (item, 'Available'); + account['total'] = this.safeString (item, 'Balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -558,7 +558,7 @@ module.exports = class bleutrade extends Exchange { // } const timestamp = this.parse8601 (this.safeString (item, 'TimeStamp')); - let amount = this.safeFloat (item, 'Amount'); + let amount = this.safeNumber (item, 'Amount'); let direction = undefined; if (amount !== undefined) { direction = 'in'; @@ -632,27 +632,12 @@ module.exports = class bleutrade extends Exchange { if ('Created' in order) { timestamp = this.parse8601 (order['Created'] + '+00:00'); } - let price = this.safeFloat (order, 'Price'); - let cost = undefined; - const amount = this.safeFloat (order, 'Quantity'); - const remaining = this.safeFloat (order, 'QuantityRemaining'); - let filled = undefined; - if (amount !== undefined && remaining !== undefined) { - filled = amount - remaining; - } - if (!cost) { - if (price && filled) { - cost = price * filled; - } - } - if (!price) { - if (cost && filled) { - price = cost / filled; - } - } - const average = this.safeFloat (order, 'PricePerUnit'); + const price = this.safeNumber (order, 'Price'); + const amount = this.safeNumber (order, 'Quantity'); + const remaining = this.safeNumber (order, 'QuantityRemaining'); + const average = this.safeNumber (order, 'PricePerUnit'); const id = this.safeString (order, 'OrderID'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -666,15 +651,15 @@ module.exports = class bleutrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -711,7 +696,7 @@ module.exports = class bleutrade extends Exchange { // Symbol: 'BTC' } // const id = this.safeString (transaction, 'ID'); - let amount = this.safeFloat (transaction, 'Amount'); + let amount = this.safeNumber (transaction, 'Amount'); let type = 'deposit'; if (amount < 0) { amount = Math.abs (amount); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/braziliex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/braziliex.js index 0c54e4840..31a519468 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/braziliex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/braziliex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -184,11 +185,11 @@ module.exports = class braziliex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': this.safeFloat (currency, 'txWithdrawalFee'), + 'fee': this.safeNumber (currency, 'txWithdrawalFee'), }, 'deposit': { 'active': canDeposit, - 'fee': this.safeFloat (currency, 'txDepositFee'), + 'fee': this.safeNumber (currency, 'txDepositFee'), }, }, 'limits': { @@ -205,11 +206,11 @@ module.exports = class braziliex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'MinWithdrawal'), + 'min': this.safeNumber (currency, 'MinWithdrawal'), 'max': Math.pow (10, precision), }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, }, @@ -257,9 +258,9 @@ module.exports = class braziliex extends Exchange { const quoteIsFiat = this.safeInteger (quoteCurrency, 'is_fiat', 0); let minCost = undefined; if (quoteIsFiat) { - minCost = this.safeFloat (baseCurrency, 'minAmountTradeFIAT'); + minCost = this.safeNumber (baseCurrency, 'minAmountTradeFIAT'); } else { - minCost = this.safeFloat (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); + minCost = this.safeNumber (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); } const isActive = this.safeInteger (market, 'active'); const active = (isActive === 1); @@ -302,27 +303,27 @@ module.exports = class braziliex extends Exchange { symbol = market['symbol']; } const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highestBid24'), - 'low': this.safeFloat (ticker, 'lowestAsk24'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'highestBid24'), + 'low': this.safeNumber (ticker, 'lowestAsk24'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'percentChange'), + 'change': this.safeNumber (ticker, 'percentChange'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume24'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume24'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24'), 'info': ticker, }; } @@ -362,13 +363,18 @@ module.exports = class braziliex extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString2 (trade, 'date_exec', 'date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } - const cost = this.safeFloat (trade, 'total'); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_number'); const type = 'limit'; const side = this.safeString (trade, 'type'); @@ -410,11 +416,11 @@ module.exports = class braziliex extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -436,21 +442,16 @@ module.exports = class braziliex extends Exchange { if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'date')); } - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'total', 0.0); - const amount = this.safeFloat (order, 'amount'); - const filledPercentage = this.safeFloat (order, 'progress'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'total'); + const amount = this.safeNumber (order, 'amount'); + const filledPercentage = this.safeNumber (order, 'progress'); const filled = amount * filledPercentage; - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); - let info = order; - if ('info' in info) { - info = order['info']; - } const id = this.safeString (order, 'order_number'); const fee = this.safeValue (order, 'fee'); // propagated from createOrder const status = (filledPercentage === 1.0) ? 'closed' : 'open'; const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -467,12 +468,12 @@ module.exports = class braziliex extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, - 'info': info, + 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -524,7 +525,7 @@ module.exports = class braziliex extends Exchange { 'price': this.safeString (priceParts, 1), 'total': this.safeString (totalParts, 1), 'fee': { - 'cost': this.safeFloat (feeParts, 1), + 'cost': this.safeNumber (feeParts, 1), 'currency': this.safeString (feeParts, 2), }, 'progress': '0.0', diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcalpha.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcalpha.js index 820234604..f7a890dfb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcalpha.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcalpha.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, DDoSProtection, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -145,8 +146,8 @@ module.exports = class btcalpha extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -198,14 +199,11 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'id', 'tid'); const side = this.safeString2 (trade, 'my_side', 'side'); const orderId = this.safeString (trade, 'o_id'); @@ -254,11 +252,11 @@ module.exports = class btcalpha extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -295,11 +293,11 @@ module.exports = class btcalpha extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'reserve'); - account['total'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserve'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -320,8 +318,8 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (order, 'date'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString2 (order, 'oid', 'id'); let trades = this.safeValue (order, 'trades', []); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcbox.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcbox.js index 1a5f82456..48a455625 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcbox.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcbox.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -88,12 +89,12 @@ module.exports = class btcbox extends Exchange { if (free in response) { const account = this.account (); const used = currencyId + '_lock'; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -114,16 +115,16 @@ module.exports = class btcbox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -133,8 +134,8 @@ module.exports = class btcbox extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -158,14 +159,11 @@ module.exports = class btcbox extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeString (trade, 'type'); return { @@ -265,15 +263,15 @@ module.exports = class btcbox extends Exchange { if (datetimeString !== undefined) { timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time } - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let cost = undefined; if (price !== undefined) { if (filled !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcmarkets.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcmarkets.js index 2340d1960..44cdd0f78 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcmarkets.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcmarkets.js @@ -246,11 +246,11 @@ module.exports = class btcmarkets extends Exchange { const tagTo = tag; const addressFrom = undefined; const tagFrom = undefined; - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const currencyId = this.safeString (transaction, 'assetName'); const code = this.safeCurrencyCode (currencyId); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (fee) { amount -= fee; } @@ -303,10 +303,10 @@ module.exports = class btcmarkets extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const fees = this.safeValue (this.safeValue (this.options, 'fees', {}), quote, this.fees); - const pricePrecision = this.safeFloat (market, 'priceDecimals'); - const amountPrecision = this.safeFloat (market, 'amountDecimals'); - const minAmount = this.safeFloat (market, 'minOrderAmount'); - const maxAmount = this.safeFloat (market, 'maxOrderAmount'); + const pricePrecision = this.safeNumber (market, 'priceDecimals'); + const amountPrecision = this.safeNumber (market, 'amountDecimals'); + const minAmount = this.safeNumber (market, 'minOrderAmount'); + const maxAmount = this.safeNumber (market, 'maxOrderAmount'); let minPrice = undefined; if (quote === 'AUD') { minPrice = Math.pow (10, -pricePrecision); @@ -365,14 +365,12 @@ module.exports = class btcmarkets extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetName'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance, 'balance'); - const used = this.safeFloat (balance, 'locked'); const account = this.account (); - account['used'] = used; - account['total'] = total; + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -388,11 +386,11 @@ module.exports = class btcmarkets extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 0)), - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 2), // high - this.safeFloat (ohlcv, 3), // low - this.safeFloat (ohlcv, 4), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 2), // high + this.safeNumber (ohlcv, 3), // low + this.safeNumber (ohlcv, 4), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -488,21 +486,21 @@ module.exports = class btcmarkets extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'lastPrice'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); - const quoteVolume = this.safeFloat (ticker, 'volumeQte24h'); + const last = this.safeNumber (ticker, 'lastPrice'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); + const quoteVolume = this.safeNumber (ticker, 'volumeQte24h'); const vwap = this.vwap (baseVolume, quoteVolume); - const change = this.safeFloat (ticker, 'price24h'); - const percentage = this.safeFloat (ticker, 'pricePct24h'); + const change = this.safeNumber (ticker, 'price24h'); + const percentage = this.safeNumber (ticker, 'pricePct24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bestBid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'bestAsk'), + 'ask': this.safeNumber (ticker, 'bestAsk'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -613,8 +611,8 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -623,7 +621,7 @@ module.exports = class btcmarkets extends Exchange { } const orderId = this.safeString (trade, 'orderId'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -714,7 +712,7 @@ module.exports = class btcmarkets extends Exchange { } } if (triggerPriceIsRequired) { - const triggerPrice = this.safeFloat (params, 'triggerPrice'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); params = this.omit (params, 'triggerPrice'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a triggerPrice parameter for a ' + type + 'order'); @@ -847,9 +845,9 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const type = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'openAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'openAmount'); let filled = undefined; if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); @@ -864,7 +862,7 @@ module.exports = class btcmarkets extends Exchange { const id = this.safeString (order, 'orderId'); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btctradeua.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btctradeua.js index 011bc33b6..32527f881 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btctradeua.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btctradeua.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -106,10 +107,10 @@ module.exports = class btctradeua extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -249,14 +250,11 @@ module.exports = class btctradeua extends Exchange { const id = this.safeString (trade, 'id'); const type = 'limit'; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amnt_trade'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amnt_trade'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -337,11 +335,11 @@ module.exports = class btctradeua extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'amnt_trade'), + 'amount': this.safeNumber (order, 'amnt_trade'), 'filled': 0, - 'remaining': this.safeFloat (order, 'amnt_trade'), + 'remaining': this.safeNumber (order, 'amnt_trade'), 'trades': undefined, 'info': order, 'cost': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcturk.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcturk.js index 32ea74550..2ef97bc99 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcturk.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/btcturk.js @@ -125,13 +125,13 @@ module.exports = class btcturk extends Exchange { const used = currency['id'] + '_reserved'; if (free in response) { const account = this.account (); - account['free'] = this.safeFloat (response, free); - account['total'] = this.safeFloat (response, total); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['total'] = this.safeString (response, total); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -151,26 +151,26 @@ module.exports = class btcturk extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'average'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -204,8 +204,8 @@ module.exports = class btcturk extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -247,11 +247,11 @@ module.exports = class btcturk extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (this.safeString (ohlcv, 'Time')), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/buda.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/buda.js index e78c228ea..ac71ec42b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/buda.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/buda.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -220,7 +221,7 @@ module.exports = class buda extends Exchange { } const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); - const precision = this.safeFloat (currency, 'input_decimals'); + const precision = this.safeNumber (currency, 'input_decimals'); const minimum = Math.pow (10, -precision); result[code] = { 'id': id, @@ -381,24 +382,25 @@ module.exports = class buda extends Exchange { let timestamp = undefined; let side = undefined; const type = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; const order = undefined; const fee = undefined; let symbol = undefined; - let cost = undefined; if (market) { symbol = market['symbol']; } if (Array.isArray (trade)) { - timestamp = parseInt (trade[0]); - price = parseFloat (trade[1]); - amount = parseFloat (trade[2]); - cost = price * amount; - side = trade[3]; - id = trade[4].toString (); + timestamp = this.safeInteger (trade, 0); + priceString = this.safeString (trade, 1); + amountString = this.safeString (trade, 2); + side = this.safeString (trade, 3); + id = this.safeString (trade, 4); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': order, @@ -453,11 +455,11 @@ module.exports = class buda extends Exchange { const currencyId = this.safeString (balance, 'id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = parseFloat (balance['available_amount'][0]); - account['total'] = parseFloat (balance['amount'][0]); + account['free'] = this.safeString (balance['available_amount'], 0); + account['total'] = this.safeString (balance['amount'], 0); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -565,15 +567,15 @@ module.exports = class buda extends Exchange { const side = this.safeStringLower (order, 'type'); const status = this.parseOrderStatus (this.safeString (order, 'state')); const originalAmount = this.safeValue (order, 'original_amount', []); - const amount = this.safeFloat (originalAmount, 0); + const amount = this.safeNumber (originalAmount, 0); const remainingAmount = this.safeValue (order, 'amount', []); - const remaining = this.safeFloat (remainingAmount, 0); + const remaining = this.safeNumber (remainingAmount, 0); const tradedAmount = this.safeValue (order, 'traded_amount', []); - const filled = this.safeFloat (tradedAmount, 0); + const filled = this.safeNumber (tradedAmount, 0); const totalExchanged = this.safeValue (order, 'totalExchanged', []); - const cost = this.safeFloat (totalExchanged, 0); + const cost = this.safeNumber (totalExchanged, 0); const limitPrice = this.safeValue (order, 'limit', []); - let price = this.safeFloat (limitPrice, 0); + let price = this.safeNumber (limitPrice, 0); if (price === undefined) { if (limitPrice !== undefined) { price = limitPrice; @@ -584,7 +586,7 @@ module.exports = class buda extends Exchange { average = this.priceToPrecision (symbol, cost / filled); } const paidFee = this.safeValue (order, 'paid_fee', []); - const feeCost = this.safeFloat (paidFee, 0); + const feeCost = this.safeNumber (paidFee, 0); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (paidFee, 1); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bw.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bw.js index 388946b39..4fb3b4192 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bw.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bw.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { RateLimitExceeded, BadSymbol, OrderNotFound, ExchangeError, AuthenticationError, ArgumentsRequired, ExchangeNotAvailable } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -185,7 +186,7 @@ module.exports = class bw extends Exchange { const symbol = base + '/' + quote; const state = this.safeInteger (market, 'state'); const active = (state === 1); - const fee = this.safeFloat (market, 'defaultFee'); + const fee = this.safeNumber (market, 'defaultFee'); result.push ({ 'id': id, 'active': active, @@ -206,7 +207,7 @@ module.exports = class bw extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -292,11 +293,11 @@ module.exports = class bw extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'drawFee'), + 'fee': this.safeNumber (currency, 'drawFee'), 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'limitAmount', 0), + 'min': this.safeNumber (currency, 'limitAmount', 0), 'max': undefined, }, 'price': { @@ -309,7 +310,7 @@ module.exports = class bw extends Exchange { }, 'withdraw': { 'min': undefined, - 'max': this.safeFloat (currency, 'onceDrawLimit'), + 'max': this.safeNumber (currency, 'onceDrawLimit'), }, }, }; @@ -346,9 +347,9 @@ module.exports = class bw extends Exchange { 'high': parseFloat (this.safeValue (ticker, 2)), 'low': parseFloat (this.safeValue (ticker, 3)), 'bid': parseFloat (this.safeValue (ticker, 7)), - 'bidVolume': this.safeFloat (bid, 'quantity'), + 'bidVolume': this.safeNumber (bid, 'quantity'), 'ask': parseFloat (this.safeValue (ticker, 8)), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, 'open': undefined, 'close': close, @@ -477,8 +478,11 @@ module.exports = class bw extends Exchange { // ... // const timestamp = this.safeTimestamp (trade, 2); - const price = this.safeFloat (trade, 5); - const amount = this.safeFloat (trade, 6); + const priceString = this.safeString (trade, 5); + const amountString = this.safeString (trade, 6); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 1); let symbol = undefined; if (marketId !== undefined) { @@ -495,12 +499,6 @@ module.exports = class bw extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const sideString = this.safeString (trade, 4); const side = (sideString === 'ask') ? 'sell' : 'buy'; return { @@ -514,7 +512,7 @@ module.exports = class bw extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': parseFloat (cost), + 'cost': cost, 'fee': undefined, 'info': trade, }; @@ -571,11 +569,11 @@ module.exports = class bw extends Exchange { // return [ this.safeTimestamp (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - this.safeFloat (ohlcv, 6), - this.safeFloat (ohlcv, 7), - this.safeFloat (ohlcv, 8), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + this.safeNumber (ohlcv, 6), + this.safeNumber (ohlcv, 7), + this.safeNumber (ohlcv, 8), ]; } @@ -633,11 +631,11 @@ module.exports = class bw extends Exchange { const currencyId = this.safeString (balance, 'currencyTypeId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'amount'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'amount'); + account['used'] = this.safeString (balance, 'freeze'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -733,25 +731,13 @@ module.exports = class bw extends Exchange { } else if (side === '1') { side = 'buy'; } - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'completeAmount'); - let remaining = this.safeFloat2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available - let cost = this.safeFloat (order, 'totalMoney'); - if (filled !== undefined) { - if (amount !== undefined) { - if (remaining === undefined) { - remaining = amount - filled; - } - } - if (cost === undefined) { - if (price !== undefined) { - cost = filled * cost; - } - } - } + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'completeAmount'); + const remaining = this.safeNumber2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available + const cost = this.safeNumber (order, 'totalMoney'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'entrustId'), 'clientOrderId': undefined, @@ -773,7 +759,7 @@ module.exports = class bw extends Exchange { 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1069,12 +1055,12 @@ module.exports = class bw extends Exchange { code = currency['code']; } const type = ('depositId' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat2 (transaction, 'actuallyAmount', 'amount'); + const amount = this.safeNumber2 (transaction, 'actuallyAmount', 'amount'); const status = this.parseTransactionStatus (this.safeString2 (transaction, 'verifyStatus', 'state')); const timestamp = this.safeInteger (transaction, 'createTime'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bybit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bybit.js index f74d0db18..7f818c6e3 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bybit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bybit.js @@ -42,6 +42,7 @@ module.exports = class bybit extends Exchange { 'fetchTrades': true, 'fetchTransactions': false, 'fetchWithdrawals': true, + 'fetchPositions': true, }, 'timeframes': { '1m': '1', @@ -73,6 +74,34 @@ module.exports = class bybit extends Exchange { 'referral': 'https://www.bybit.com/app/register?ref=X7Prm', }, 'api': { + 'futures': { + 'private': { + 'get': [ + 'position/list', + 'order/list', + 'order', + 'stop-order/list', + 'stop-order', + 'execution/list', + 'trade/closed-pnl/list', + ], + 'post': [ + 'order/create', + 'order/cancel', + 'order/cancelAll', + 'order/replace', + 'stop-order/create', + 'stop-order/cancel', + 'stop-order/cancelAll', + 'stop-order/replace', + 'position/change-position-margin', + 'position/trading-stop', + 'position/leverage/save', + 'position/switch-mode', + 'position/switch-isolated', + ], + }, + }, 'v2': { 'public': { 'get': [ @@ -286,7 +315,11 @@ module.exports = class bybit extends Exchange { 'LTC/USDT': 'linear', 'XTZ/USDT': 'linear', 'LINK/USDT': 'linear', + 'ADA/USDT': 'linear', + 'DOT/USDT': 'linear', + 'UNI/USDT': 'linear', }, + 'defaultType': 'linear', // may also be inverse or inverseFuture 'code': 'BTC', 'cancelAllOrders': { // 'method': 'v2PrivatePostOrderCancelAll', // v2PrivatePostStopOrderCancelAll @@ -401,8 +434,8 @@ module.exports = class bybit extends Exchange { const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {}); const priceFilter = this.safeValue (market, 'price_filter', {}); const precision = { - 'amount': this.safeFloat (lotSizeFilter, 'qty_step'), - 'price': this.safeFloat (priceFilter, 'tick_size'), + 'amount': this.safeNumber (lotSizeFilter, 'qty_step'), + 'price': this.safeNumber (priceFilter, 'tick_size'), }; const status = this.safeString (market, 'status'); let active = undefined; @@ -416,8 +449,8 @@ module.exports = class bybit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'type': 'future', 'spot': false, 'future': true, @@ -426,12 +459,12 @@ module.exports = class bybit extends Exchange { 'inverse': inverse, 'limits': { 'amount': { - 'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'), - 'max': this.safeFloat (lotSizeFilter, 'max_trading_qty'), + 'min': this.safeNumber (lotSizeFilter, 'min_trading_qty'), + 'max': this.safeNumber (lotSizeFilter, 'max_trading_qty'), }, 'price': { - 'min': this.safeFloat (priceFilter, 'min_price'), - 'max': this.safeFloat (priceFilter, 'max_price'), + 'min': this.safeNumber (priceFilter, 'min_price'), + 'max': this.safeNumber (priceFilter, 'max_price'), }, 'cost': { 'min': undefined, @@ -477,9 +510,9 @@ module.exports = class bybit extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const open = this.safeFloat (ticker, 'prev_price_24h'); - let percentage = this.safeFloat (ticker, 'price_24h_pcnt'); + const last = this.safeNumber (ticker, 'last_price'); + const open = this.safeNumber (ticker, 'prev_price_24h'); + let percentage = this.safeNumber (ticker, 'price_24h_pcnt'); if (percentage !== undefined) { percentage *= 100; } @@ -489,18 +522,18 @@ module.exports = class bybit extends Exchange { change = last - open; average = this.sum (open, last) / 2; } - const baseVolume = this.safeFloat (ticker, 'turnover_24h'); - const quoteVolume = this.safeFloat (ticker, 'volume_24h'); + const baseVolume = this.safeNumber (ticker, 'turnover_24h'); + const quoteVolume = this.safeNumber (ticker, 'volume_24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price_24h'), - 'low': this.safeFloat (ticker, 'low_price_24h'), - 'bid': this.safeFloat (ticker, 'bid_price'), + 'high': this.safeNumber (ticker, 'high_price_24h'), + 'low': this.safeNumber (ticker, 'low_price_24h'), + 'bid': this.safeNumber (ticker, 'bid_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask_price'), + 'ask': this.safeNumber (ticker, 'ask_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -649,11 +682,11 @@ module.exports = class bybit extends Exchange { // return [ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat2 (ohlcv, 'turnover', 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber2 (ohlcv, 'turnover', 'volume'), ]; } @@ -779,9 +812,9 @@ module.exports = class bybit extends Exchange { const marketId = this.safeString (trade, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat2 (trade, 'qty', 'exec_qty'); - let cost = this.safeFloat (trade, 'exec_value'); - const price = this.safeFloat2 (trade, 'exec_price', 'price'); + const amount = this.safeNumber2 (trade, 'qty', 'exec_qty'); + let cost = this.safeNumber (trade, 'exec_value'); + const price = this.safeNumber2 (trade, 'exec_price', 'price'); if (cost === undefined) { if (amount !== undefined) { if (price !== undefined) { @@ -796,14 +829,14 @@ module.exports = class bybit extends Exchange { const side = this.safeStringLower (trade, 'side'); const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind'); const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker'; - const feeCost = this.safeFloat (trade, 'exec_fee'); + const feeCost = this.safeNumber (trade, 'exec_fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyCode = market['inverse'] ? market['base'] : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'fee_rate'), + 'rate': this.safeNumber (trade, 'fee_rate'), }; } return { @@ -963,12 +996,12 @@ module.exports = class bybit extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['used'] = this.safeFloat (balance, 'used_margin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'used_margin'); + account['total'] = this.safeString (balance, 'equity'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -1095,56 +1128,42 @@ module.exports = class bybit extends Exchange { // const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); - let symbol = undefined; - let base = undefined; + const symbol = market['symbol']; + let feeCurrency = undefined; const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const id = this.safeString2 (order, 'order_id', 'stop_order_id'); const type = this.safeStringLower (order, 'order_type'); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - let average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'qty'); - let cost = this.safeFloat (order, 'cum_exec_value'); - let filled = this.safeFloat (order, 'cum_exec_qty'); - let remaining = this.safeFloat (order, 'leaves_qty'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'qty'); + const cost = this.safeNumber (order, 'cum_exec_value'); + const filled = this.safeNumber (order, 'cum_exec_qty'); + const remaining = this.safeNumber (order, 'leaves_qty'); + const marketTypes = this.safeValue (this.options, 'marketTypes', {}); + const marketType = this.safeString (marketTypes, symbol); if (market !== undefined) { - symbol = market['symbol']; - base = market['base']; + if (marketType === 'linear') { + feeCurrency = market['quote']; + } else { + feeCurrency = market['base']; + } } let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time'); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = amount - remaining; - } - if (filled !== undefined) { - if ((remaining === undefined) && (amount !== undefined)) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if ((type === 'market') && (cost !== undefined) && (cost > 0)) { - price = undefined; - if (average === undefined) { - average = filled / cost; - } - } - } const status = this.parseOrderStatus (this.safeString2 (order, 'order_status', 'stop_order_status')); const side = this.safeStringLower (order, 'side'); - let feeCost = this.safeFloat (order, 'cum_exec_fee'); + let feeCost = this.safeNumber (order, 'cum_exec_fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); fee = { 'cost': feeCost, - 'currency': base, + 'currency': feeCurrency, }; } let clientOrderId = this.safeString (order, 'order_link_id'); @@ -1152,9 +1171,9 @@ module.exports = class bybit extends Exchange { clientOrderId = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'stop_px'); + const stopPrice = this.safeNumber (order, 'stop_px'); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1176,7 +1195,7 @@ module.exports = class bybit extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -2027,7 +2046,8 @@ module.exports = class bybit extends Exchange { const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); + const type = this.safeStringLower (transaction, 'type'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -2047,8 +2067,8 @@ module.exports = class bybit extends Exchange { 'tag': undefined, 'tagTo': undefined, 'tagFrom': undefined, - 'type': 'withdrawal', - 'amount': this.safeFloat (transaction, 'amount'), + 'type': type, + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -2131,8 +2151,8 @@ module.exports = class bybit extends Exchange { // const currencyId = this.safeString (item, 'coin'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'wallet_balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'wallet_balance'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -2198,7 +2218,8 @@ module.exports = class bybit extends Exchange { 'recv_window': this.options['recvWindow'], 'timestamp': timestamp, }); - const auth = this.rawencode (this.keysort (query)); + const sortedQuery = this.keysort (query); + const auth = this.rawencode (sortedQuery); const signature = this.hmac (this.encode (auth), this.encode (this.secret)); if (method === 'POST') { body = this.json (this.extend (query, { @@ -2208,7 +2229,7 @@ module.exports = class bybit extends Exchange { 'Content-Type': 'application/json', }; } else { - request += '?' + auth + '&sign=' + signature; + request += '?' + this.urlencode (sortedQuery) + '&sign=' + signature; } } url += request; @@ -2231,12 +2252,43 @@ module.exports = class bybit extends Exchange { // time_now: '1583934106.590436' // } // - const errorCode = this.safeValue (response, 'ret_code'); - if (errorCode !== 0) { + const errorCode = this.safeString (response, 'ret_code'); + if (errorCode !== '0') { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback); this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback); throw new ExchangeError (feedback); // unknown message } } + + async fetchPositions (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (Array.isArray (symbols)) { + const length = symbols.length; + if (length !== 1) { + throw new ArgumentsRequired (this.id + ' fetchPositions takes exactly one symbol'); + } + request['symbol'] = this.marketId (symbols[0]); + } + const defaultType = this.safeString (this.options, 'defaultType', 'linear'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + let response = undefined; + if (type === 'linear') { + response = await this.privateLinearGetPositionList (this.extend (request, params)); + } else if (type === 'inverse') { + response = await this.v2PrivateGetPositionList (this.extend (request, params)); + } else if (type === 'inverseFuture') { + response = await this.futuresPrivateGetPositionList (this.extend (request, params)); + } + // { + // ret_code: 0, + // ret_msg: 'OK', + // ext_code: '', + // ext_info: '', + // result: [] or {} depending on the request + // } + return this.safeValue (response, 'result'); + } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bytetrade.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bytetrade.js index 25953b6f7..ad0c929d8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bytetrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bytetrade.js @@ -186,12 +186,12 @@ module.exports = class bytetrade extends Exchange { const limits = this.safeValue (currency, 'limits'); const deposit = this.safeValue (limits, 'deposit'); const amountPrecision = this.safeInteger (currency, 'basePrecision'); - let maxDeposit = this.safeFloat (deposit, 'max'); + let maxDeposit = this.safeNumber (deposit, 'max'); if (maxDeposit === -1.0) { maxDeposit = undefined; } const withdraw = this.safeValue (limits, 'withdraw'); - let maxWithdraw = this.safeFloat (withdraw, 'max'); + let maxWithdraw = this.safeNumber (withdraw, 'max'); if (maxWithdraw === -1.0) { maxWithdraw = undefined; } @@ -207,11 +207,11 @@ module.exports = class bytetrade extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (deposit, 'min'), + 'min': this.safeNumber (deposit, 'min'), 'max': maxDeposit, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'min'), + 'min': this.safeNumber (withdraw, 'min'), 'max': maxWithdraw, }, }, @@ -265,12 +265,12 @@ module.exports = class bytetrade extends Exchange { 'normalSymbol': normalSymbol, 'limits': { 'amount': { - 'min': this.safeFloat (amount, 'min'), - 'max': this.safeFloat (amount, 'max'), + 'min': this.safeNumber (amount, 'min'), + 'max': this.safeNumber (amount, 'max'), }, 'price': { - 'min': this.safeFloat (price, 'min'), - 'max': this.safeFloat (price, 'max'), + 'min': this.safeNumber (price, 'min'), + 'max': this.safeNumber (price, 'max'), }, 'cost': { 'min': undefined, @@ -298,11 +298,11 @@ module.exports = class bytetrade extends Exchange { const currencyId = this.safeString (balance, 'code'); const code = this.safeCurrencyCode (currencyId, undefined); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'used'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'used'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -363,22 +363,22 @@ module.exports = class bytetrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'open'), - 'close': this.safeFloat (ticker, 'close'), - 'last': this.safeFloat (ticker, 'last'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'open'), + 'close': this.safeNumber (ticker, 'close'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, // previous day close - 'change': this.safeFloat (ticker, 'change'), - 'percentage': this.safeFloat (ticker, 'percentage'), + 'change': this.safeNumber (ticker, 'change'), + 'percentage': this.safeNumber (ticker, 'percentage'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -421,24 +421,16 @@ module.exports = class bytetrade extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetDepth (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetDepth (params); + return this.parseTickers (response, symbols); } async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetTickers (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetTickers (params); + return this.parseTickers (response, symbols); } parseOHLCV (ohlcv, market = undefined) { @@ -454,11 +446,11 @@ module.exports = class bytetrade extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -488,9 +480,9 @@ module.exports = class bytetrade extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeInteger (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - const cost = this.safeFloat (trade, 'cost'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + const cost = this.safeNumber (trade, 'cost'); const id = this.safeString (trade, 'id'); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'takerOrMaker'); @@ -560,12 +552,12 @@ module.exports = class bytetrade extends Exchange { const timestamp = this.safeInteger (order, 'timestamp'); const datetime = this.safeString (order, 'datetime'); const lastTradeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled'); - const remaining = this.safeFloat (order, 'remaining'); - const cost = this.safeFloat (order, 'cost'); - const average = this.safeFloat (order, 'average'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled'); + const remaining = this.safeNumber (order, 'remaining'); + const cost = this.safeNumber (order, 'cost'); + const average = this.safeNumber (order, 'average'); const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); @@ -958,7 +950,7 @@ module.exports = class bytetrade extends Exchange { }; } - async transfer (code, amount, address, message = '', params = {}) { + async transfer (code, amount, fromAccount, toAccount, params = {}) { this.checkRequiredDependencies (); if (this.apiKey === undefined) { throw new ArgumentsRequired ('transfer() requires this.apiKey'); @@ -976,6 +968,7 @@ module.exports = class bytetrade extends Exchange { expirationDatetime = expirationDatetime.split ('.')[0]; const feeAmount = '300000000000000'; const defaultDappId = 'Sagittarius'; + const message = this.safeString (params, 'message', ''); const dappId = this.safeString (params, 'dappId', defaultDappId); const eightBytes = this.integerPow ('2', '64'); const byteStringArray = [ @@ -989,8 +982,8 @@ module.exports = class bytetrade extends Exchange { this.numberToLE (feeAmount, 8), // string for 32 bit php this.numberToLE (this.apiKey.length, 1), this.stringToBinary (this.encode (this.apiKey)), - this.numberToLE (address.length, 1), - this.stringToBinary (this.encode (address)), + this.numberToLE (toAccount.length, 1), + this.stringToBinary (this.encode (toAccount)), this.numberToLE (assetType, 4), this.numberToLE (this.integerDivide (amountChain, eightBytes), 8), this.numberToLE (this.integerModulo (amountChain, eightBytes), 8), @@ -1011,7 +1004,7 @@ module.exports = class bytetrade extends Exchange { const operation = { 'fee': '300000000000000', 'from': this.apiKey, - 'to': address, + 'to': toAccount, 'asset_type': parseInt (currency['id']), 'amount': amountChain.toString (), 'message': message, @@ -1165,9 +1158,9 @@ module.exports = class bytetrade extends Exchange { const datetime = this.safeString (transaction, 'datetime'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const feeInfo = this.safeValue (transaction, 'fee'); - const feeCost = this.safeFloat (feeInfo, 'cost'); + const feeCost = this.safeNumber (feeInfo, 'cost'); const feeCurrencyId = this.safeString (feeInfo, 'code'); const feeCode = this.safeCurrencyCode (feeCurrencyId, currency); const fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/cex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/cex.js index 77473d391..876830762 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/cex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/cex.js @@ -256,7 +256,7 @@ module.exports = class cex extends Exchange { 'fee': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimumCurrencyAmount'), + 'min': this.safeNumber (currency, 'minimumCurrencyAmount'), 'max': undefined, }, 'price': { @@ -268,7 +268,7 @@ module.exports = class cex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimalWithdrawalAmount'), + 'min': this.safeNumber (currency, 'minimalWithdrawalAmount'), 'max': undefined, }, }, @@ -351,15 +351,15 @@ module.exports = class cex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minLotSize'), - 'max': this.safeFloat (market, 'maxLotSize'), + 'min': this.safeNumber (market, 'minLotSize'), + 'max': this.safeNumber (market, 'maxLotSize'), }, 'price': { - 'min': this.safeFloat (market, 'minPrice'), - 'max': this.safeFloat (market, 'maxPrice'), + 'min': this.safeNumber (market, 'minPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { - 'min': this.safeFloat (market, 'minLotSizeS2'), + 'min': this.safeNumber (market, 'minLotSizeS2'), 'max': undefined, }, }, @@ -380,13 +380,13 @@ module.exports = class cex extends Exchange { const currencyId = currencyIds[i]; const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); + account['free'] = this.safeString (balance, 'available'); // https://github.com/ccxt/ccxt/issues/5484 - account['used'] = this.safeFloat (balance, 'orders', 0.0); + account['used'] = this.safeString (balance, 'orders', '0'); const code = this.safeCurrencyCode (currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -415,11 +415,11 @@ module.exports = class cex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -461,12 +461,12 @@ module.exports = class cex extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const volume = this.safeFloat (ticker, 'volume'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'last'); + const volume = this.safeNumber (ticker, 'volume'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'last'); let symbol = undefined; if (market) { symbol = market['symbol']; @@ -528,8 +528,8 @@ module.exports = class cex extends Exchange { const id = this.safeString (trade, 'tid'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -601,8 +601,8 @@ module.exports = class cex extends Exchange { // "complete": false // } // - const placedAmount = this.safeFloat (response, 'amount'); - const remaining = this.safeFloat (response, 'pending'); + const placedAmount = this.safeNumber (response, 'amount'); + const remaining = this.safeNumber (response, 'pending'); const timestamp = this.safeValue (response, 'time'); const complete = this.safeValue (response, 'complete'); const status = complete ? 'closed' : 'open'; @@ -621,7 +621,7 @@ module.exports = class cex extends Exchange { 'side': this.safeString (response, 'type'), 'symbol': symbol, 'status': status, - 'price': this.safeFloat (response, 'price'), + 'price': this.safeNumber (response, 'price'), 'amount': placedAmount, 'cost': undefined, 'average': undefined, @@ -663,42 +663,42 @@ module.exports = class cex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - let amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + let amount = this.safeNumber (order, 'amount'); // sell orders can have a negative amount // https://github.com/ccxt/ccxt/issues/5338 if (amount !== undefined) { amount = Math.abs (amount); } - const remaining = this.safeFloat2 (order, 'pending', 'remains'); + const remaining = this.safeNumber2 (order, 'pending', 'remains'); const filled = amount - remaining; let fee = undefined; let cost = undefined; if (market !== undefined) { symbol = market['symbol']; - const taCost = this.safeFloat (order, 'ta:' + market['quote']); - const ttaCost = this.safeFloat (order, 'tta:' + market['quote']); + const taCost = this.safeNumber (order, 'ta:' + market['quote']); + const ttaCost = this.safeNumber (order, 'tta:' + market['quote']); cost = this.sum (taCost, ttaCost); const baseFee = 'fa:' + market['base']; const baseTakerFee = 'tfa:' + market['base']; const quoteFee = 'fa:' + market['quote']; const quoteTakerFee = 'tfa:' + market['quote']; - let feeRate = this.safeFloat (order, 'tradingFeeMaker'); + let feeRate = this.safeNumber (order, 'tradingFeeMaker'); if (!feeRate) { - feeRate = this.safeFloat (order, 'tradingFeeTaker', feeRate); + feeRate = this.safeNumber (order, 'tradingFeeTaker', feeRate); } if (feeRate) { feeRate /= 100.0; // convert to mathematically-correct percentage coefficients: 1.0 = 100% } if ((baseFee in order) || (baseTakerFee in order)) { - const baseFeeCost = this.safeFloat2 (order, baseFee, baseTakerFee); + const baseFeeCost = this.safeNumber2 (order, baseFee, baseTakerFee); fee = { 'currency': market['base'], 'rate': feeRate, 'cost': baseFeeCost, }; } else if ((quoteFee in order) || (quoteTakerFee in order)) { - const quoteFeeCost = this.safeFloat2 (order, quoteFee, quoteTakerFee); + const quoteFeeCost = this.safeNumber2 (order, quoteFee, quoteTakerFee); fee = { 'currency': market['quote'], 'rate': feeRate, @@ -738,7 +738,7 @@ module.exports = class cex extends Exchange { // ds: 0 } continue; } - const tradePrice = this.safeFloat (item, 'price'); + const tradePrice = this.safeNumber (item, 'price'); if (tradePrice === undefined) { // this represents the order // { @@ -842,8 +842,8 @@ module.exports = class cex extends Exchange { // "fee_amount": "0.03" // } const tradeTimestamp = this.parse8601 (this.safeString (item, 'time')); - const tradeAmount = this.safeFloat (item, 'amount'); - const feeCost = this.safeFloat (item, 'fee_amount'); + const tradeAmount = this.safeNumber (item, 'amount'); + const feeCost = this.safeNumber (item, 'fee_amount'); let absTradeAmount = (tradeAmount < 0) ? -tradeAmount : tradeAmount; let tradeCost = undefined; if (tradeSide === 'sell') { @@ -1188,12 +1188,12 @@ module.exports = class cex extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const side = this.safeString (order, 'type'); - const baseAmount = this.safeFloat (order, 'a:' + baseId + ':cds'); - const quoteAmount = this.safeFloat (order, 'a:' + quoteId + ':cds'); - const fee = this.safeFloat (order, 'f:' + quoteId + ':cds'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const remaining = this.safeFloat (order, 'remains'); + const baseAmount = this.safeNumber (order, 'a:' + baseId + ':cds'); + const quoteAmount = this.safeNumber (order, 'a:' + quoteId + ':cds'); + const fee = this.safeNumber (order, 'f:' + quoteId + ':cds'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const remaining = this.safeNumber (order, 'remains'); const filled = amount - remaining; let orderAmount = undefined; let cost = undefined; @@ -1205,10 +1205,10 @@ module.exports = class cex extends Exchange { cost = quoteAmount; average = orderAmount / cost; } else { - const ta = this.safeFloat (order, 'ta:' + quoteId, 0); - const tta = this.safeFloat (order, 'tta:' + quoteId, 0); - const fa = this.safeFloat (order, 'fa:' + quoteId, 0); - const tfa = this.safeFloat (order, 'tfa:' + quoteId, 0); + const ta = this.safeNumber (order, 'ta:' + quoteId, 0); + const tta = this.safeNumber (order, 'tta:' + quoteId, 0); + const fa = this.safeNumber (order, 'fa:' + quoteId, 0); + const tfa = this.safeNumber (order, 'tfa:' + quoteId, 0); if (side === 'sell') { cost = this.sum (this.sum (ta, tta), this.sum (fa, tfa)); } else { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/chilebit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/chilebit.js deleted file mode 100644 index 4aeeb9ec3..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/chilebit.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const foxbit = require ('./foxbit.js'); - -// --------------------------------------------------------------------------- - -module.exports = class chilebit extends foxbit { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'chilebit', - 'name': 'ChileBit', - 'countries': [ 'CL' ], - 'has': { - 'CORS': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg', - 'api': { - 'public': 'https://api.blinktrade.com/api', - 'private': 'https://api.blinktrade.com/tapi', - }, - 'www': 'https://chilebit.net', - 'doc': 'https://blinktrade.com/docs', - }, - 'options': { - 'brokerId': '9', // https://blinktrade.com/docs/#brokers - }, - }); - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbase.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbase.js index cfceba2a4..1413a7064 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbase.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbase.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, RateLimitExceeded, InvalidNonce } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -411,10 +412,10 @@ module.exports = class coinbase extends Exchange { const timestamp = this.parse8601 (this.safeValue (transaction, 'created_at')); const updated = this.parse8601 (this.safeValue (transaction, 'updated_at')); const type = this.safeString (transaction, 'resource'); - const amount = this.safeFloat (subtotalObject, 'amount'); + const amount = this.safeNumber (subtotalObject, 'amount'); const currencyId = this.safeString (subtotalObject, 'currency'); const currency = this.safeCurrencyCode (currencyId); - const feeCost = this.safeFloat (feeObject, 'amount'); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -490,15 +491,12 @@ module.exports = class coinbase extends Exchange { const orderId = undefined; const side = this.safeString (trade, 'resource'); const type = undefined; - const cost = this.safeFloat (subtotalObject, 'amount'); - const amount = this.safeFloat (amountObject, 'amount'); - let price = undefined; - if (cost !== undefined) { - if ((amount !== undefined) && (amount > 0)) { - price = cost / amount; - } - } - const feeCost = this.safeFloat (feeObject, 'amount'); + const costString = this.safeString (subtotalObject, 'amount'); + const amountString = this.safeString (amountObject, 'amount'); + const cost = this.parseNumber (costString); + const amount = this.parseNumber (amountString); + const price = this.parseNumber (Precise.stringDiv (costString, amountString)); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -566,7 +564,7 @@ module.exports = class coinbase extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (quoteCurrency, 'min_size'), + 'min': this.safeNumber (quoteCurrency, 'min_size'), 'max': undefined, }, }, @@ -648,7 +646,7 @@ module.exports = class coinbase extends Exchange { 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min_size'), + 'min': this.safeNumber (currency, 'min_size'), 'max': undefined, }, 'price': { @@ -679,9 +677,9 @@ module.exports = class coinbase extends Exchange { const buy = await this.publicGetPricesSymbolBuy (request); const sell = await this.publicGetPricesSymbolSell (request); const spot = await this.publicGetPricesSymbolSpot (request); - const ask = this.safeFloat (buy['data'], 'amount'); - const bid = this.safeFloat (sell['data'], 'amount'); - const last = this.safeFloat (spot['data'], 'amount'); + const ask = this.safeNumber (buy['data'], 'amount'); + const bid = this.safeNumber (sell['data'], 'amount'); + const last = this.safeNumber (spot['data'], 'amount'); return { 'symbol': symbol, 'timestamp': timestamp, @@ -724,7 +722,7 @@ module.exports = class coinbase extends Exchange { if (this.inArray (balance['type'], accounts)) { const currencyId = this.safeString (balance['balance'], 'currency'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance['balance'], 'amount'); + const total = this.safeNumber (balance['balance'], 'amount'); const free = total; const used = undefined; if (code in result) { @@ -1025,7 +1023,7 @@ module.exports = class coinbase extends Exchange { // } // const amountInfo = this.safeValue (item, 'amount', {}); - let amount = this.safeFloat (amountInfo, 'amount'); + let amount = this.safeNumber (amountInfo, 'amount'); let direction = undefined; if (amount < 0) { direction = 'out'; @@ -1051,7 +1049,7 @@ module.exports = class coinbase extends Exchange { if (feeInfo !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId, currency); - const feeAmount = this.safeFloat (feeInfo, 'amount'); + const feeAmount = this.safeNumber (feeInfo, 'amount'); fee = { 'cost': feeAmount, 'currency': feeCurrencyCode, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbasepro.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbasepro.js index 582c03a61..6d8c48454 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbasepro.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinbasepro.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound, OnMaintenance, PermissionDenied, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -239,7 +240,7 @@ module.exports = class coinbasepro extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const details = this.safeValue (currency, 'details', {}); - const precision = this.safeFloat (currency, 'max_precision'); + const precision = this.safeNumber (currency, 'max_precision'); const status = this.safeString (currency, 'status'); const active = (status === 'online'); result[code] = { @@ -253,7 +254,7 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (details, 'min_size'), + 'min': this.safeNumber (details, 'min_size'), 'max': undefined, }, 'price': { @@ -265,7 +266,7 @@ module.exports = class coinbasepro extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (details, 'min_withdrawal_amount'), + 'min': this.safeNumber (details, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -309,12 +310,12 @@ module.exports = class coinbasepro extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const priceLimits = { - 'min': this.safeFloat (market, 'quote_increment'), + 'min': this.safeNumber (market, 'quote_increment'), 'max': undefined, }; const precision = { - 'amount': this.safeFloat (market, 'base_increment'), - 'price': this.safeFloat (market, 'quote_increment'), + 'amount': this.safeNumber (market, 'base_increment'), + 'price': this.safeNumber (market, 'quote_increment'), }; const status = this.safeString (market, 'status'); const active = (status === 'online'); @@ -328,13 +329,13 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': priceLimits, 'cost': { - 'min': this.safeFloat (market, 'min_market_funds'), - 'max': this.safeFloat (market, 'max_market_funds'), + 'min': this.safeNumber (market, 'min_market_funds'), + 'max': this.safeNumber (market, 'max_market_funds'), }, }, 'active': active, @@ -391,14 +392,13 @@ module.exports = class coinbasepro extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'hold'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'hold'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -455,29 +455,29 @@ module.exports = class coinbasepro extends Exchange { // } // const timestamp = this.parse8601 (this.safeValue (ticker, 'time')); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'price'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'price'); const symbol = (market === undefined) ? undefined : market['symbol']; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': undefined, 'ask': ask, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -550,7 +550,7 @@ module.exports = class coinbasepro extends Exchange { if (market !== undefined) { const feeCurrencyId = this.safeStringLower (market, 'quoteId'); const costField = feeCurrencyId + '_value'; - cost = this.safeFloat (trade, costField); + cost = this.safeNumber (trade, costField); feeCurrency = market['quote']; const liquidity = this.safeString (trade, 'liquidity'); if (liquidity !== undefined) { @@ -558,7 +558,7 @@ module.exports = class coinbasepro extends Exchange { feeRate = market[takerOrMaker]; } } - const feeCost = this.safeFloat2 (trade, 'fill_fees', 'fee'); + const feeCost = this.safeNumber2 (trade, 'fill_fees', 'fee'); const fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -572,10 +572,12 @@ module.exports = class coinbasepro extends Exchange { if (orderId !== undefined) { side = (trade['side'] === 'buy') ? 'buy' : 'sell'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - cost = amount * price; + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -637,11 +639,11 @@ module.exports = class coinbasepro extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -721,17 +723,11 @@ module.exports = class coinbasepro extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'filled_size'); - const amount = this.safeFloat (order, 'size', filled); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'executed_value'); - const feeCost = this.safeFloat (order, 'fill_fees'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'filled_size'); + const amount = this.safeNumber (order, 'size', filled); + const cost = this.safeNumber (order, 'executed_value'); + const feeCost = this.safeNumber (order, 'fill_fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -749,9 +745,9 @@ module.exports = class coinbasepro extends Exchange { const side = this.safeString (order, 'side'); const timeInForce = this.safeString (order, 'time_in_force'); const postOnly = this.safeValue (order, 'post_only'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -769,11 +765,11 @@ module.exports = class coinbasepro extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -863,7 +859,7 @@ module.exports = class coinbasepro extends Exchange { request['client_oid'] = clientOrderId; params = this.omit (params, [ 'clientOrderId', 'client_oid' ]); } - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop_price'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stop_price'); if (stopPrice !== undefined) { request['stop_price'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, [ 'stopPrice', 'stop_price' ]); @@ -877,7 +873,7 @@ module.exports = class coinbasepro extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['size'] = this.amountToPrecision (symbol, amount); } else if (type === 'market') { - let cost = this.safeFloat2 (params, 'cost', 'funds'); + let cost = this.safeNumber2 (params, 'cost', 'funds'); if (cost === undefined) { if (price !== undefined) { cost = amount * price; @@ -948,19 +944,6 @@ module.exports = class coinbasepro extends Exchange { return await this.privateDeleteOrders (this.extend (request, params)); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - const cost = amount * price; - const currency = market['quote']; - return { - 'type': takerOrMaker, - 'currency': currency, - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (currency, rate * cost)), - }; - } - async fetchPaymentMethods (params = {}) { return await this.privateGetPaymentMethods (params); } @@ -1099,7 +1082,7 @@ module.exports = class coinbasepro extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (transaction); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let type = this.safeString (transaction, 'type'); let address = this.safeString (details, 'crypto_address'); const tag = this.safeString (details, 'destination_tag'); @@ -1108,7 +1091,7 @@ module.exports = class coinbasepro extends Exchange { if (type === 'withdraw') { type = 'withdrawal'; address = this.safeString (details, 'sent_to_address', address); - const feeCost = this.safeFloat (details, 'fee'); + const feeCost = this.safeNumber (details, 'fee'); if (feeCost !== undefined) { if (amount !== undefined) { amount -= feeCost; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coincheck.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coincheck.js index 807882d02..e7a3db265 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coincheck.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coincheck.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -127,12 +128,12 @@ module.exports = class coincheck extends Exchange { if (currencyId in balances) { const account = this.account (); const reserved = currencyId + '_reserved'; - account['free'] = this.safeFloat (balances, currencyId); - account['used'] = this.safeFloat (balances, reserved); + account['free'] = this.safeString (balances, currencyId); + account['used'] = this.safeString (balances, reserved); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -170,23 +171,13 @@ module.exports = class coincheck extends Exchange { const id = this.safeString (order, 'id'); const side = this.safeString (order, 'order_type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const amount = this.safeFloat (order, 'pending_amount'); - const remaining = this.safeFloat (order, 'pending_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = Math.max (amount - remaining, 0); - if (price !== undefined) { - cost = filled * price; - } - } - } + const amount = this.safeNumber (order, 'pending_amount'); + const remaining = this.safeNumber (order, 'pending_amount'); + const price = this.safeNumber (order, 'rate'); const status = undefined; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -194,7 +185,7 @@ module.exports = class coincheck extends Exchange { 'lastTradeTimestamp': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'side': side, 'type': undefined, 'timeInForce': undefined, @@ -203,12 +194,12 @@ module.exports = class coincheck extends Exchange { 'symbol': symbol, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'info': order, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -232,16 +223,16 @@ module.exports = class coincheck extends Exchange { }; const ticker = await this.publicGetTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -251,7 +242,7 @@ module.exports = class coincheck extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -260,7 +251,7 @@ module.exports = class coincheck extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'rate'); + const priceString = this.safeString (trade, 'rate'); const marketId = this.safeString (trade, 'pair'); market = this.safeValue (this.markets_by_id, marketId, market); let symbol = undefined; @@ -287,7 +278,7 @@ module.exports = class coincheck extends Exchange { } } let takerOrMaker = undefined; - let amount = undefined; + let amountString = undefined; let cost = undefined; let side = undefined; let fee = undefined; @@ -299,24 +290,22 @@ module.exports = class coincheck extends Exchange { takerOrMaker = 'maker'; } const funds = this.safeValue (trade, 'funds', {}); - amount = this.safeFloat (funds, baseId); - cost = this.safeFloat (funds, quoteId); + amountString = this.safeString (funds, baseId); + cost = this.safeNumber (funds, quoteId); fee = { 'currency': this.safeString (trade, 'fee_currency'), - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), }; side = this.safeString (trade, 'side'); orderId = this.safeString (trade, 'order_id'); } else { - amount = this.safeFloat (trade, 'amount'); + amountString = this.safeString (trade, 'amount'); side = this.safeString (trade, 'order_type'); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -387,6 +376,10 @@ module.exports = class coincheck extends Exchange { return await this.privateDeleteExchangeOrdersId (this.extend (request, params)); } + nonce () { + return this.milliseconds (); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { let url = this.urls['api'] + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinegg.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinegg.js index e270e3bf7..0b2e2ef89 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinegg.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinegg.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -214,8 +215,8 @@ module.exports = class coinegg extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; let change = undefined; let average = undefined; @@ -229,11 +230,11 @@ module.exports = class coinegg extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -243,8 +244,8 @@ module.exports = class coinegg extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVol'), 'info': ticker, }; } @@ -273,15 +274,12 @@ module.exports = class coinegg extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const type = 'limit'; const side = this.safeString (trade, 'type'); const id = this.safeString (trade, 'tid'); @@ -328,9 +326,9 @@ module.exports = class coinegg extends Exchange { result[code] = this.account (); } const type = (accountType === 'lock') ? 'used' : 'free'; - result[code][type] = this.safeFloat (balances, key); + result[code][type] = this.safeString (balances, key); } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -339,15 +337,9 @@ module.exports = class coinegg extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let status = this.safeString (order, 'status'); if (status === 'cancelled') { status = 'canceled'; @@ -358,7 +350,7 @@ module.exports = class coinegg extends Exchange { const type = 'limit'; const side = this.safeString (order, 'type'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -374,13 +366,13 @@ module.exports = class coinegg extends Exchange { 'stopPrice': undefined, 'cost': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'trades': undefined, 'fee': undefined, 'info': info, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinex.js index cc344ee72..575d0f239 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, OrderNotFound, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -196,13 +197,13 @@ module.exports = class coinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': this.safeFloat (market, 'taker_fee_rate'), - 'maker': this.safeFloat (market, 'maker_fee_rate'), + 'taker': this.safeNumber (market, 'taker_fee_rate'), + 'maker': this.safeNumber (market, 'maker_fee_rate'), 'info': market, 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -222,16 +223,16 @@ module.exports = class coinex extends Exchange { symbol = market['symbol']; } ticker = this.safeValue (ticker, 'ticker', {}); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -241,7 +242,7 @@ module.exports = class coinex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat2 (ticker, 'vol', 'volume'), + 'baseVolume': this.safeNumber2 (ticker, 'vol', 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -301,16 +302,18 @@ module.exports = class coinex extends Exchange { } const tradeId = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market); - let cost = this.safeFloat (trade, 'deal_money'); - if (!cost) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); + let cost = this.safeNumber (trade, 'deal_money'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_asset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -363,11 +366,11 @@ module.exports = class coinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -428,11 +431,11 @@ module.exports = class coinex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -471,11 +474,11 @@ module.exports = class coinex extends Exchange { // } // const timestamp = this.safeTimestamp (order, 'create_time'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'deal_money'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'deal_amount'); - const average = this.safeFloat (order, 'avg_price'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'deal_money'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'deal_amount'); + const average = this.safeNumber (order, 'avg_price'); let symbol = undefined; const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); @@ -487,11 +490,11 @@ module.exports = class coinex extends Exchange { feeCurrency = market['quote']; } } - const remaining = this.safeFloat (order, 'left'); + const remaining = this.safeNumber (order, 'left'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -513,10 +516,10 @@ module.exports = class coinex extends Exchange { 'trades': undefined, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'deal_fee'), + 'cost': this.safeNumber (order, 'deal_fee'), }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -762,8 +765,8 @@ module.exports = class coinex extends Exchange { const timestamp = this.safeTimestamp (transaction, 'create_time'); const type = ('coin_withdraw_id' in transaction) ? 'withdraw' : 'deposit'; const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'tx_fee'); + let amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'tx_fee'); if (type === 'deposit') { feeCost = 0; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfalcon.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfalcon.js index 6c264b4ec..8d3077293 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfalcon.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfalcon.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, RateLimitExceeded, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -136,11 +137,11 @@ module.exports = class coinfalcon extends Exchange { 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'change_in_24h'), + 'change': this.safeNumber (ticker, 'change_in_24h'), 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -177,20 +178,17 @@ module.exports = class coinfalcon extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } const tradeId = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'order_id'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = this.safeString (trade, 'fee_currency_code'); fee = { @@ -258,14 +256,13 @@ module.exports = class coinfalcon extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available_balance'), - 'used': this.safeFloat (balance, 'hold_balance'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'hold_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -300,19 +297,9 @@ module.exports = class coinfalcon extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'size_filled'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (price !== undefined) { - cost = filled * price; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'size_filled'); const status = this.parseOrderStatus (this.safeString (order, 'status')); let type = this.safeString (order, 'operation_type'); if (type !== undefined) { @@ -321,7 +308,7 @@ module.exports = class coinfalcon extends Exchange { } const side = this.safeString (order, 'order_type'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -334,16 +321,16 @@ module.exports = class coinfalcon extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'lastTradeTimestamp': undefined, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfloor.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfloor.js index 7fff650de..790ac8c50 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfloor.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinfloor.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ExchangeError, InvalidNonce, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -105,14 +106,14 @@ module.exports = class coinfloor extends Exchange { const baseIdLower = this.safeStringLower (market, 'baseId'); const quoteIdLower = this.safeStringLower (market, 'quoteId'); result[base] = { - 'free': this.safeFloat (response, baseIdLower + '_available'), - 'used': this.safeFloat (response, baseIdLower + '_reserved'), - 'total': this.safeFloat (response, baseIdLower + '_balance'), + 'free': this.safeNumber (response, baseIdLower + '_available'), + 'used': this.safeNumber (response, baseIdLower + '_reserved'), + 'total': this.safeNumber (response, baseIdLower + '_balance'), }; result[quote] = { - 'free': this.safeFloat (response, quoteIdLower + '_available'), - 'used': this.safeFloat (response, quoteIdLower + '_reserved'), - 'total': this.safeFloat (response, quoteIdLower + '_balance'), + 'free': this.safeNumber (response, quoteIdLower + '_available'), + 'used': this.safeNumber (response, quoteIdLower + '_reserved'), + 'total': this.safeNumber (response, quoteIdLower + '_balance'), }; return this.parseBalance (result); } @@ -133,22 +134,22 @@ module.exports = class coinfloor extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -177,14 +178,11 @@ module.exports = class coinfloor extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -302,8 +300,8 @@ module.exports = class coinfloor extends Exchange { const parts = key.split ('_'); const numParts = parts.length; if (numParts === 2) { - const tmpBaseAmount = this.safeFloat (item, parts[0]); - const tmpQuoteAmount = this.safeFloat (item, parts[1]); + const tmpBaseAmount = this.safeNumber (item, parts[0]); + const tmpQuoteAmount = this.safeNumber (item, parts[1]); if (tmpBaseAmount !== undefined && tmpQuoteAmount !== undefined) { baseId = parts[0]; quoteId = parts[1]; @@ -319,7 +317,7 @@ module.exports = class coinfloor extends Exchange { const referenceId = this.safeString (item, 'id'); const timestamp = this.parse8601 (this.safeString (item, 'datetime')); let fee = undefined; - const feeCost = this.safeFloat (item, 'fee'); + const feeCost = this.safeNumber (item, 'fee'); const result = { 'id': undefined, 'timestamp': timestamp, @@ -423,8 +421,8 @@ module.exports = class coinfloor extends Exchange { 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, 'type': type, - 'price': this.safeFloat (response, 'price'), - 'remaining': this.safeFloat (response, 'amount'), + 'price': this.safeNumber (response, 'price'), + 'remaining': this.safeNumber (response, 'amount'), 'info': response, }; } @@ -449,19 +447,14 @@ module.exports = class coinfloor extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let side = undefined; const status = this.safeString (order, 'status'); - if (order['type'] === 0) { + const rawType = this.safeString (order, 'type'); + if (rawType === '0') { side = 'buy'; - } else if (order['type'] === 1) { + } else if (rawType === '1') { side = 'sell'; } let symbol = undefined; @@ -469,7 +462,7 @@ module.exports = class coinfloor extends Exchange { symbol = market['symbol']; } const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -487,11 +480,11 @@ module.exports = class coinfloor extends Exchange { 'amount': undefined, 'filled': undefined, 'remaining': amount, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coingi.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coingi.js index 650d80885..931325ea6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coingi.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coingi.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -165,14 +166,14 @@ module.exports = class coingi extends Exchange { const currencyId = this.safeString (balance['currency'], 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - const blocked = this.safeFloat (balance, 'blocked'); - const inOrders = this.safeFloat (balance, 'inOrders'); - const withdrawing = this.safeFloat (balance, 'withdrawing'); - account['used'] = this.sum (blocked, inOrders, withdrawing); + account['free'] = this.safeString (balance, 'available'); + const blocked = this.safeString (balance, 'blocked'); + const inOrders = this.safeString (balance, 'inOrders'); + const withdrawing = this.safeString (balance, 'withdrawing'); + account['used'] = Precise.stringAdd (Precise.stringAdd (blocked, inOrders), withdrawing); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = 512, params = {}) { @@ -198,11 +199,11 @@ module.exports = class coingi extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -212,8 +213,8 @@ module.exports = class coingi extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'counterVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'counterVolume'), 'info': ticker, }; } @@ -246,14 +247,11 @@ module.exports = class coingi extends Exchange { } parseTrade (trade, market = undefined) { - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const id = this.safeString (trade, 'id'); const marketId = this.safeString (trade, 'currencyPair'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmarketcap.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmarketcap.js index 171a65889..85edd4882 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmarketcap.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmarketcap.js @@ -208,16 +208,16 @@ module.exports = class coinmarketcap extends Exchange { if (timestamp === undefined) { timestamp = this.milliseconds (); } - const change = this.safeFloat (ticker, 'percent_change_24h'); + const change = this.safeNumber (ticker, 'percent_change_24h'); let last = undefined; let symbol = undefined; let volume = undefined; if (market !== undefined) { symbol = market['symbol']; const priceKey = 'price_' + market['quoteId']; - last = this.safeFloat (ticker, priceKey); + last = this.safeNumber (ticker, priceKey); const volumeKey = '24h_volume_' + market['quoteId']; - volume = this.safeFloat (ticker, volumeKey); + volume = this.safeNumber (ticker, volumeKey); } return { 'symbol': symbol, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmate.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmate.js index b03ce8783..821e5d7e8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmate.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinmate.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder, OrderNotFound, RateLimitExceeded, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -230,7 +231,7 @@ module.exports = class coinmate extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -258,12 +259,12 @@ module.exports = class coinmate extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -286,16 +287,16 @@ module.exports = class coinmate extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'data'); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'vwap': undefined, 'askVolume': undefined, 'open': undefined, @@ -305,7 +306,7 @@ module.exports = class coinmate extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'amount'), + 'baseVolume': this.safeNumber (ticker, 'amount'), 'quoteVolume': undefined, 'info': ticker, }; @@ -374,8 +375,8 @@ module.exports = class coinmate extends Exchange { // } // const timestamp = this.safeInteger (item, 'timestamp'); - const amount = this.safeFloat (item, 'amount'); - const fee = this.safeFloat (item, 'fee'); + const amount = this.safeNumber (item, 'amount'); + const fee = this.safeNumber (item, 'fee'); const txid = this.safeString (item, 'txid'); const address = this.safeString (item, 'destination'); const tag = this.safeString (item, 'destinationTag'); @@ -453,21 +454,18 @@ module.exports = class coinmate extends Exchange { // const marketId = this.safeString (trade, 'currencyPair'); market = this.safeMarket (marketId, market, '_'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeStringLower2 (trade, 'type', 'tradeType'); const type = this.safeStringLower (trade, 'orderType'); const orderId = this.safeString (trade, 'orderId'); const id = this.safeString (trade, 'transactionId'); const timestamp = this.safeInteger2 (trade, 'timestamp', 'createdTimestamp'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -608,11 +606,11 @@ module.exports = class coinmate extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.safeInteger (order, 'timestamp'); const side = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'originalAmount'); - let remaining = this.safeFloat (order, 'remainingAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'originalAmount'); + let remaining = this.safeNumber (order, 'remainingAmount'); if (remaining === undefined) { - remaining = this.safeFloat (order, 'amount'); + remaining = this.safeNumber (order, 'amount'); } let status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.parseOrderType (this.safeString (order, 'orderTradeType')); @@ -627,11 +625,11 @@ module.exports = class coinmate extends Exchange { cost = filled * price; } } - const average = this.safeFloat (order, 'avgPrice'); + const average = this.safeNumber (order, 'avgPrice'); const marketId = this.safeString (order, 'currencyPair'); const symbol = this.safeSymbol (marketId, market, '_'); const clientOrderId = this.safeString (order, 'clientOrderId'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); return { 'id': id, 'clientOrderId': clientOrderId, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinone.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinone.js index 0c86365b6..cd0f3585c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinone.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinone.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, BadRequest, ExchangeError, ArgumentsRequired, OrderNotFound, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -142,11 +143,11 @@ module.exports = class coinone extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'avail'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -199,13 +200,13 @@ module.exports = class coinone extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const first = this.safeFloat (ticker, 'first'); - const last = this.safeFloat (ticker, 'last'); + const first = this.safeNumber (ticker, 'first'); + const last = this.safeNumber (ticker, 'last'); let average = undefined; if (first !== undefined && last !== undefined) { average = this.sum (first, last) / 2; } - const previousClose = this.safeFloat (ticker, 'yesterday_last'); + const previousClose = this.safeNumber (ticker, 'yesterday_last'); let change = undefined; let percentage = undefined; if (last !== undefined && previousClose !== undefined) { @@ -219,8 +220,8 @@ module.exports = class coinone extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -233,7 +234,7 @@ module.exports = class coinone extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -279,20 +280,17 @@ module.exports = class coinone extends Exchange { side = 'buy'; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'fee'); + let feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); - let feeRate = this.safeFloat (trade, 'feeRate'); + let feeRate = this.safeNumber (trade, 'feeRate'); feeRate = Math.abs (feeRate); let feeCurrencyCode = undefined; if (market !== undefined) { @@ -452,7 +450,7 @@ module.exports = class coinone extends Exchange { // } // const id = this.safeString (order, 'orderId'); - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); const timestamp = this.safeTimestamp (order, 'timestamp'); let side = this.safeString (order, 'type'); if (side === 'ask') { @@ -460,9 +458,8 @@ module.exports = class coinone extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const remaining = this.safeFloat (order, 'remainQty'); - let filled = undefined; - const amount = this.safeFloat (order, 'qty'); + const remaining = this.safeNumber (order, 'remainQty'); + const amount = this.safeNumber (order, 'qty'); let status = this.safeString (order, 'status'); // https://github.com/ccxt/ccxt/pull/7067 if (status === 'live') { @@ -472,14 +469,7 @@ module.exports = class coinone extends Exchange { } } } - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (amount - remaining); - } status = this.parseOrderStatus (status); - let cost = undefined; - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } let symbol = undefined; let base = undefined; let quote = undefined; @@ -499,16 +489,16 @@ module.exports = class coinone extends Exchange { quote = market['quote']; } let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = (side === 'sell') ? quote : base; fee = { 'cost': feeCost, - 'rate': this.safeFloat (order, 'feeRate'), + 'rate': this.safeNumber (order, 'feeRate'), 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -522,15 +512,15 @@ module.exports = class coinone extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': amount, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -605,8 +595,8 @@ module.exports = class coinone extends Exchange { // eslint-disable-next-line quotes throw new ArgumentsRequired (this.id + " cancelOrder() requires a symbol argument. To cancel the order, pass a symbol argument and {'price': 12345, 'qty': 1.2345, 'is_ask': 0} in the params argument of cancelOrder."); } - const price = this.safeFloat (params, 'price'); - const qty = this.safeFloat (params, 'qty'); + const price = this.safeNumber (params, 'price'); + const qty = this.safeNumber (params, 'qty'); const isAsk = this.safeInteger (params, 'is_ask'); if ((price === undefined) || (qty === undefined) || (isAsk === undefined)) { // eslint-disable-next-line quotes diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinspot.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinspot.js index e04c42b5d..63c9b3fd2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinspot.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/coinspot.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -123,7 +124,7 @@ module.exports = class coinspot extends Exchange { const balance = currencies[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } } @@ -133,11 +134,11 @@ module.exports = class coinspot extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -157,16 +158,16 @@ module.exports = class coinspot extends Exchange { id = id.toLowerCase (); const ticker = response['prices'][id]; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -214,11 +215,13 @@ module.exports = class coinspot extends Exchange { // "market":"BTC/AUD" // } // - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'total'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger (trade, 'solddate'); const marketId = this.safeString (trade, 'market'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/crex24.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/crex24.js index 7c1298090..5c3a3ccde 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/crex24.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/crex24.js @@ -4,6 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, InvalidNonce, RequestTimeout, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, AuthenticationError, BadSymbol } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110,6 +112,7 @@ module.exports = class crex24 extends Exchange { ], }, }, + 'precisionMode': TICK_SIZE, 'fees': { 'trading': { 'tierBased': true, @@ -130,6 +133,7 @@ module.exports = class crex24 extends Exchange { 'BIT': 'BitMoney', 'BULL': 'BuySell', 'CREDIT': 'TerraCredit', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'GHOST': 'GHOSTPRISM', 'IQ': 'IQ.Cash', 'PUT': 'PutinCoin', @@ -163,6 +167,7 @@ module.exports = class crex24 extends Exchange { 'API Key': AuthenticationError, // "API Key '9edc48de-d5b0-4248-8e7e-f59ffcd1c7f1' doesn't exist." 'Insufficient funds': InsufficientFunds, // "Insufficient funds: new order requires 10 ETH which is more than the available balance." 'has been delisted.': BadSymbol, // {"errorDescription":"Instrument '$PAC-BTC' has been delisted."} + 'is currently suspended.': BadSymbol, // {"errorDescription":"Trading in BITG-BTC is currently suspended."} 'Mandatory parameter': BadRequest, // {"errorDescription":"Mandatory parameter 'feeCurrency' is missing."} }, }, @@ -204,12 +209,12 @@ module.exports = class crex24 extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const tickSize = this.safeValue (market, 'tickSize'); - const minPrice = this.safeValue (market, 'minPrice'); - const minAmount = this.safeFloat (market, 'minVolume'); + const tickSize = this.safeNumber (market, 'tickSize'); + const minPrice = this.safeNumber (market, 'minPrice'); + const minAmount = this.safeNumber (market, 'minVolume'); const precision = { - 'amount': this.precisionFromString (this.numberToString (minAmount)), - 'price': this.precisionFromString (this.numberToString (tickSize)), + 'amount': minAmount, + 'price': tickSize, }; const active = (market['state'] === 'active'); result.push ({ @@ -274,7 +279,8 @@ module.exports = class crex24 extends Exchange { const currency = response[i]; const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); - const precision = this.safeInteger (currency, 'withdrawalPrecision'); + const withdrawalPrecision = this.safeInteger (currency, 'withdrawalPrecision'); + const precision = Math.pow (10, -withdrawalPrecision); const address = this.safeValue (currency, 'BaseAddress'); const active = (currency['depositsAllowed'] && currency['withdrawalsAllowed'] && !currency['isDelisted']); const type = currency['isFiat'] ? 'fiat' : 'crypto'; @@ -286,7 +292,7 @@ module.exports = class crex24 extends Exchange { 'type': type, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'flatWithdrawalFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'flatWithdrawalFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -302,12 +308,12 @@ module.exports = class crex24 extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -337,11 +343,11 @@ module.exports = class crex24 extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -393,16 +399,16 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); const marketId = this.safeString (ticker, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -410,10 +416,10 @@ module.exports = class crex24 extends Exchange { 'last': last, 'previousClose': undefined, // previous day close 'change': undefined, - 'percentage': this.safeFloat (ticker, 'percentChange'), + 'percentage': this.safeNumber (ticker, 'percentChange'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -483,14 +489,6 @@ module.exports = class crex24 extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - parseTrade (trade, market = undefined) { // // public fetchTrades @@ -515,14 +513,11 @@ module.exports = class crex24 extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'orderId'); @@ -531,7 +526,7 @@ module.exports = class crex24 extends Exchange { let fee = undefined; const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCode = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -592,11 +587,11 @@ module.exports = class crex24 extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -665,50 +660,19 @@ module.exports = class crex24 extends Exchange { const marketId = this.safeString (order, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remainingVolume'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remainingVolume'); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'lastUpdate')); - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = amount - remaining; - if (this.options['parseOrderToPrecision']) { - filled = parseFloat (this.amountToPrecision (symbol, filled)); - } - filled = Math.max (filled, 0.0); - if (price !== undefined) { - cost = price * filled; - } - } - } const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeString (order, 'side'); const fee = undefined; const trades = undefined; - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const average = undefined; const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -722,14 +686,14 @@ module.exports = class crex24 extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -764,7 +728,7 @@ module.exports = class crex24 extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -1183,8 +1147,8 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'createdAt')); const updated = this.parse8601 (this.safeString (transaction, 'processedAt')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); const fee = { 'cost': feeCost, 'currency': code, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/currencycom.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/currencycom.js index c8570f1d4..17aa6bfa5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/currencycom.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/currencycom.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -92,6 +93,7 @@ module.exports = class currencycom extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.002, @@ -250,7 +252,7 @@ module.exports = class currencycom extends Exchange { const filtersByType = this.indexBy (filters, 'filterType'); const precision = { 'amount': 1 / Math.pow (1, this.safeInteger (market, 'baseAssetPrecision')), - 'price': this.safeFloat (market, 'tickSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'TRADING'); @@ -283,14 +285,14 @@ module.exports = class currencycom extends Exchange { 'max': undefined, }, 'cost': { - 'min': -1 * Math.log10 (precision['amount']), + 'min': -Math.log10 (precision['amount']), 'max': undefined, }, }, }; - const exchangeFee = this.safeFloat2 (market, 'exchangeFee', 'tradingFee'); - const makerFee = this.safeFloat (market, 'makerFee', exchangeFee); - const takerFee = this.safeFloat (market, 'takerFee', exchangeFee); + const exchangeFee = this.safeNumber2 (market, 'exchangeFee', 'tradingFee'); + const makerFee = this.safeNumber (market, 'makerFee', exchangeFee); + const takerFee = this.safeNumber (market, 'takerFee', exchangeFee); if (makerFee !== undefined) { entry['maker'] = makerFee / 100; } @@ -299,65 +301,44 @@ module.exports = class currencycom extends Exchange { } if ('PRICE_FILTER' in filtersByType) { const filter = this.safeValue (filtersByType, 'PRICE_FILTER', {}); - entry['precision']['price'] = this.safeFloat (filter, 'tickSize'); + entry['precision']['price'] = this.safeNumber (filter, 'tickSize'); // PRICE_FILTER reports zero values for maxPrice // since they updated filter types in November 2018 // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } } if ('LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'LOT_SIZE', {}); - entry['precision']['amount'] = this.safeFloat (filter, 'stepSize'); + entry['precision']['amount'] = this.safeNumber (filter, 'stepSize'); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat (filter, 'minNotional'); + entry['limits']['cost']['min'] = this.safeNumber (filter, 'minNotional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { const response = await this.privateGetAccount (params); // @@ -404,8 +385,8 @@ module.exports = class currencycom extends Exchange { const response = await this.privateGetAccount (params); return { 'info': response, - 'maker': this.safeFloat (response, 'makerCommission'), - 'taker': this.safeFloat (response, 'takerCommission'), + 'maker': this.safeNumber (response, 'makerCommission'), + 'taker': this.safeNumber (response, 'takerCommission'), }; } @@ -439,11 +420,11 @@ module.exports = class currencycom extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -542,8 +523,8 @@ module.exports = class currencycom extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); - const open = this.safeFloat (ticker, 'openPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); let average = undefined; if ((open !== undefined) && (last !== undefined)) { average = this.sum (open, last) / 2; @@ -552,22 +533,22 @@ module.exports = class currencycom extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), 'open': open, 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -602,14 +583,6 @@ module.exports = class currencycom extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24hr (params); @@ -642,11 +615,11 @@ module.exports = class currencycom extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -712,8 +685,11 @@ module.exports = class currencycom extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -729,7 +705,7 @@ module.exports = class currencycom extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -751,7 +727,7 @@ module.exports = class currencycom extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': fee, }; } @@ -827,66 +803,21 @@ module.exports = class currencycom extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); + const remaining = undefined; + const cost = this.safeNumber (order, 'cummulativeQuoteQty'); const id = this.safeString (order, 'orderId'); const type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeStringLower (order, 'side'); - let fee = undefined; let trades = undefined; const fills = this.safeValue (order, 'fills'); if (fills !== undefined) { trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'timestamp': timestamp, @@ -900,13 +831,13 @@ module.exports = class currencycom extends Exchange { 'stopPrice': undefined, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/delta.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/delta.js index 9b3c559bf..028cdf3ac 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/delta.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/delta.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, BadRequest, BadSymbol, InvalidOrder, AuthenticationError, ArgumentsRequired, OrderNotFound, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -258,14 +259,14 @@ module.exports = class delta extends Exchange { 'name': this.safeString (currency, 'name'), 'info': currency, // the original payload 'active': active, - 'fee': this.safeFloat (currency, 'base_withdrawal_fee'), + 'fee': this.safeNumber (currency, 'base_withdrawal_fee'), 'precision': 1 / Math.pow (10, precision), 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal_amount'), + 'min': this.safeNumber (currency, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -399,26 +400,26 @@ module.exports = class delta extends Exchange { } const precision = { 'amount': 1.0, // number of contracts - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; const limits = { 'amount': { 'min': 1.0, - 'max': this.safeFloat (market, 'position_size_limit'), + 'max': this.safeNumber (market, 'position_size_limit'), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; const state = this.safeString (market, 'state'); const active = (state === 'live'); - const maker = this.safeFloat (market, 'maker_commission_rate'); - const taker = this.safeFloat (market, 'taker_commission_rate'); + const maker = this.safeNumber (market, 'maker_commission_rate'); + const taker = this.safeNumber (market, 'taker_commission_rate'); result.push ({ 'id': id, 'numericId': numericId, @@ -466,8 +467,8 @@ module.exports = class delta extends Exchange { const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.001); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; let percentage = undefined; @@ -478,15 +479,15 @@ module.exports = class delta extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'turnover'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'turnover'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -656,12 +657,11 @@ module.exports = class delta extends Exchange { const orderId = this.safeString (trade, 'order_id'); let timestamp = this.parse8601 (this.safeString (trade, 'created_at')); timestamp = this.safeIntegerProduct (trade, 'timestamp', 0.001, timestamp); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const product = this.safeValue (trade, 'product', {}); const marketId = this.safeString (product, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -680,7 +680,7 @@ module.exports = class delta extends Exchange { if (type !== undefined) { type = type.replace ('_order', ''); } - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { const settlingAsset = this.safeValue (product, 'settling_asset', {}); @@ -747,11 +747,11 @@ module.exports = class delta extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -821,11 +821,11 @@ module.exports = class delta extends Exchange { const currency = this.safeValue (currenciesByNumericId, currencyId); const code = (currency === undefined) ? currencyId : currency['code']; const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchPosition (symbol, params = undefined) { @@ -849,7 +849,7 @@ module.exports = class delta extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPositionsMargined (params); // @@ -930,20 +930,12 @@ module.exports = class delta extends Exchange { const side = this.safeString (order, 'side'); let type = this.safeString (order, 'order_type'); type = type.replace ('_order', ''); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'unfilled_size'); - let filled = undefined; - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let cost = undefined; - const average = this.safeFloat (order, 'average_fill_price'); - if ((average !== undefined) && filled) { - cost = average * filled; - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'unfilled_size'); + const average = this.safeNumber (order, 'average_fill_price'); let fee = undefined; - const feeCost = this.safeFloat (order, 'paid_commission'); + const feeCost = this.safeNumber (order, 'paid_commission'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -956,7 +948,7 @@ module.exports = class delta extends Exchange { 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -968,14 +960,14 @@ module.exports = class delta extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1374,9 +1366,9 @@ module.exports = class delta extends Exchange { const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId'); currency = this.safeValue (currenciesByNumericId, currencyId, currency); const code = (currency === undefined) ? undefined : currency['code']; - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'created_at')); - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const before = Math.max (0, after - amount); const status = 'ok'; return { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/deribit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/deribit.js index f277c3975..1a7c91bec 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/deribit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/deribit.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, DDoSProtection, NotSupported, ExchangeNotAvailable, InsufficientFunds, BadRequest, InvalidAddress, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -435,8 +436,8 @@ module.exports = class deribit extends Exchange { const future = (type === 'future'); const option = (type === 'option'); const active = this.safeValue (market, 'is_active'); - const minTradeAmount = this.safeFloat (market, 'min_trade_amount'); - const tickSize = this.safeFloat (market, 'tick_size'); + const minTradeAmount = this.safeNumber (market, 'min_trade_amount'); + const tickSize = this.safeNumber (market, 'tick_size'); const precision = { 'amount': minTradeAmount, 'price': tickSize, @@ -448,8 +449,8 @@ module.exports = class deribit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_commission'), - 'maker': this.safeFloat (market, 'maker_commission'), + 'taker': this.safeNumber (market, 'taker_commission'), + 'maker': this.safeNumber (market, 'maker_commission'), 'limits': { 'amount': { 'min': minTradeAmount, @@ -532,11 +533,11 @@ module.exports = class deribit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const currencyCode = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableFunds'); - account['used'] = this.safeFloat (balance, 'maintenanceMargin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'maintenanceMargin'); + account['total'] = this.safeString (balance, 'equity'); result[currencyCode] = account; - return this.parseBalance (result); + return this.parseBalance (result, false); } async createDepositAddress (code, params = {}) { @@ -654,18 +655,18 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger2 (ticker, 'timestamp', 'creation_timestamp'); const marketId = this.safeString (ticker, 'instrument_name'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat2 (ticker, 'last_price', 'last'); + const last = this.safeNumber2 (ticker, 'last_price', 'last'); const stats = this.safeValue (ticker, 'stats', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (stats, 'high', 'max_price'), - 'low': this.safeFloat2 (stats, 'low', 'min_price'), - 'bid': this.safeFloat2 (ticker, 'best_bid_price', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_amount'), - 'ask': this.safeFloat2 (ticker, 'best_ask_price', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_amount'), + 'high': this.safeNumber2 (stats, 'high', 'max_price'), + 'low': this.safeNumber2 (stats, 'low', 'min_price'), + 'bid': this.safeNumber2 (ticker, 'best_bid_price', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_amount'), + 'ask': this.safeNumber2 (ticker, 'best_ask_price', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_amount'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -675,7 +676,7 @@ module.exports = class deribit extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (stats, 'volume'), + 'quoteVolume': this.safeNumber (stats, 'volume'), 'info': ticker, }; } @@ -862,21 +863,18 @@ module.exports = class deribit extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const liquidity = this.safeString (trade, 'liquidity'); let takerOrMaker = undefined; if (liquidity !== undefined) { // M = maker, T = taker, MT = both takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -1056,31 +1054,21 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger (order, 'creation_timestamp'); const lastUpdate = this.safeInteger (order, 'last_update_timestamp'); const id = this.safeString (order, 'order_id'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); let lastTradeTimestamp = undefined; if (filled !== undefined) { if (filled > 0) { lastTradeTimestamp = lastUpdate; } } - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = price * filled; - } - } const status = this.parseOrderStatus (this.safeString (order, 'order_state')); const marketId = this.safeString (order, 'instrument_name'); market = this.safeMarket (marketId, market); const side = this.safeStringLower (order, 'direction'); - let feeCost = this.safeFloat (order, 'commission'); + let feeCost = this.safeNumber (order, 'commission'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); @@ -1098,7 +1086,7 @@ module.exports = class deribit extends Exchange { const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); const stopPrice = this.safeValue (order, 'stop_price'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1113,14 +1101,14 @@ module.exports = class deribit extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1197,7 +1185,7 @@ module.exports = class deribit extends Exchange { } } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price or stopPrice param for a ' + type + ' order'); } else { @@ -1596,7 +1584,7 @@ module.exports = class deribit extends Exchange { const updated = this.safeInteger (transaction, 'updated_timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let type = 'deposit'; let fee = undefined; if (feeCost !== undefined) { @@ -1619,7 +1607,7 @@ module.exports = class deribit extends Exchange { 'tagTo': undefined, 'tagFrom': undefined, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -1665,7 +1653,7 @@ module.exports = class deribit extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.codeFromOptions ('fetchPositions'); const currency = this.currency (code); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/digifinex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/digifinex.js index 6584b919c..528126688 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/digifinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/digifinex.js @@ -3,7 +3,8 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); -const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -61,11 +62,6 @@ module.exports = class digifinex extends Exchange { 'referral': 'https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp', }, 'api': { - 'v2': { - 'get': [ - 'ticker', - ], - }, 'public': { 'get': [ '{market}/symbols', @@ -191,6 +187,7 @@ module.exports = class digifinex extends Exchange { }, 'commonCurrencies': { 'BHT': 'Black House Test', + 'EPS': 'Epanus', 'MBN': 'Mobilian Coin', 'TEL': 'TEL666', }, @@ -245,7 +242,7 @@ module.exports = class digifinex extends Exchange { const depositStatus = this.safeValue (currency, 'deposit_status', 1); const withdrawStatus = this.safeValue (currency, 'withdraw_status', 1); const active = depositStatus && withdrawStatus; - const fee = this.safeFloat (currency, 'withdraw_fee_rate'); + const fee = this.safeNumber (currency, 'withdraw_fee_rate'); if (code in result) { if (Array.isArray (result[code]['info'])) { result[code]['info'].push (currency); @@ -276,7 +273,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw_amount'), + 'min': this.safeNumber (currency, 'min_withdraw_amount'), 'max': undefined, }, }, @@ -330,7 +327,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), 'max': undefined, }, 'price': { @@ -338,7 +335,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), + 'min': this.safeNumber (market, 'minimum_value'), 'max': undefined, }, }; @@ -352,7 +349,7 @@ module.exports = class digifinex extends Exchange { // const status = this.safeString (market, 'status'); // const active = (status === 'TRADING'); // - const isAllowed = this.safeValue (market, 'is_allow', 1); + const isAllowed = this.safeInteger (market, 'is_allow', 1); const active = isAllowed ? true : false; const type = 'spot'; const spot = (type === 'spot'); @@ -408,7 +405,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), + 'min': this.safeNumber (market, 'min_volume'), 'max': undefined, }, 'price': { @@ -416,7 +413,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, }; @@ -461,12 +458,12 @@ module.exports = class digifinex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -500,87 +497,67 @@ module.exports = class digifinex extends Exchange { } async fetchTickers (symbols = undefined, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTickers() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); - const request = { - 'apiKey': apiKey, - }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (params); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const result = {}; - const tickers = this.safeValue (response, 'ticker', {}); + const tickers = this.safeValue (response, 'ticker', []); const date = this.safeInteger (response, 'date'); - const reversedMarketIds = Object.keys (tickers); - for (let i = 0; i < reversedMarketIds.length; i++) { - const reversedMarketId = reversedMarketIds[i]; - const ticker = this.extend ({ + for (let i = 0; i < tickers.length; i++) { + const rawTicker = this.extend ({ 'date': date, - }, tickers[reversedMarketId]); - const [ quoteId, baseId ] = reversedMarketId.split ('_'); - const marketId = baseId.toUpperCase () + '_' + quoteId.toUpperCase (); - const market = this.safeMarket (marketId, undefined, '_'); - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); + }, tickers[i]); + const ticker = this.parseTicker (rawTicker); + const symbol = ticker['symbol']; + result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTicker (symbol, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTicker() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); const market = this.market (symbol); - // reversed base/quote in v2 - const marketId = market['quoteId'].toLowerCase () + '_' + market['baseId'].toLowerCase (); const request = { - 'symbol': marketId, - 'apiKey': apiKey, + 'symbol': market['id'], }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (this.extend (request, params)); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const date = this.safeInteger (response, 'date'); - const ticker = this.safeValue (response, 'ticker', {}); - let result = this.safeValue (ticker, marketId, {}); - result = this.extend ({ 'date': date }, result); + const tickers = this.safeValue (response, 'ticker', []); + const firstTicker = this.safeValue (tickers, 0, {}); + const result = this.extend ({ 'date': date }, firstTicker); return this.parseTicker (result, market); } @@ -590,6 +567,7 @@ module.exports = class digifinex extends Exchange { // // { // "last":0.021957, + // "symbol": "btc_usdt", // "base_vol":2249.3521732227, // "change":-0.6, // "vol":102443.5111, @@ -600,22 +578,20 @@ module.exports = class digifinex extends Exchange { // "date"1564518452, // injected from fetchTicker/fetchTickers // } // - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeStringUpper (ticker, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -625,8 +601,8 @@ module.exports = class digifinex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'base_vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'base_vol'), 'info': ticker, }; } @@ -662,18 +638,15 @@ module.exports = class digifinex extends Exchange { const orderId = this.safeString (trade, 'order_id'); const timestamp = this.safeTimestamp2 (trade, 'date', 'timestamp'); const side = this.safeString2 (trade, 'type', 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); const takerOrMaker = this.safeValue (trade, 'is_maker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -775,11 +748,11 @@ module.exports = class digifinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 5), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 1), // volume + this.safeNumber (ohlcv, 5), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 1), // volume ]; } @@ -970,21 +943,11 @@ module.exports = class digifinex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_price'); - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - return { + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1000,13 +963,13 @@ module.exports = class digifinex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'average': average, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1200,7 +1163,7 @@ module.exports = class digifinex extends Exchange { const code = this.safeCurrencyCode (this.safeString (item, 'currency_mark'), currency); const timestamp = this.safeTimestamp (item, 'time'); const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -1263,16 +1226,6 @@ module.exports = class digifinex extends Exchange { return this.parseLedger (items, currency, since, limit); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -1425,8 +1378,8 @@ module.exports = class digifinex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_date')); const updated = this.parse8601 (this.safeString (transaction, 'finished_date')); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -1476,7 +1429,7 @@ module.exports = class digifinex extends Exchange { } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const version = (api === 'v2') ? api : this.version; + const version = this.version; let url = this.urls['api'] + '/' + version + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); const urlencoded = this.urlencode (this.keysort (query)); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/dsx.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/dsx.js deleted file mode 100644 index 349fc2489..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/dsx.js +++ /dev/null @@ -1,1274 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, BadRequest, InsufficientFunds, PermissionDenied, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class dsx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'dsx', - 'name': 'DSX', - 'countries': [ 'UK' ], - 'rateLimit': 1500, - 'version': 'v3', - 'has': { - 'cancelOrder': true, - 'CORS': false, - 'createDepositAddress': true, - 'createMarketOrder': false, - 'createOrder': true, - 'fetchBalance': true, - 'fetchClosedOrders': false, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOHLCV': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchOrderBooks': true, - 'fetchOrders': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTransactions': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg', - 'api': { - 'public': 'https://dsxglobal.com/mapi', // market data - 'private': 'https://dsxglobal.com/tapi', // trading - 'dwapi': 'https://dsxglobal.com/dwapi', // deposit/withdraw - }, - 'www': 'https://dsxglobal.com', - 'doc': [ - 'https://dsxglobal.com/developers/publicApi', - ], - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'maker': 0.15 / 100, - 'taker': 0.25 / 100, - }, - }, - 'timeframes': { - '1m': 'm', - '1h': 'h', - '1d': 'd', - }, - 'api': { - // market data (public) - 'public': { - 'get': [ - 'barsFromMoment/{pair}/{period}/{start}', - 'depth/{pair}', - 'info', - 'lastBars/{pair}/{period}/{amount}', // period is 'm', 'h' or 'd' - 'periodBars/{pair}/{period}/{start}/{end}', - 'ticker/{pair}', - 'trades/{pair}', - ], - }, - // trading (private) - 'private': { - 'post': [ - 'info/account', - 'history/transactions', - 'history/trades', - 'history/orders', - 'orders', - 'order/cancel', - // 'order/cancel/all', - 'order/status', - 'order/new', - 'volume', - 'fees', // trading fee schedule - ], - }, - // deposit / withdraw (private) - 'dwapi': { - 'post': [ - 'deposit/cryptoaddress', - 'withdraw/crypto', - 'withdraw/fiat', - 'withdraw/submit', - // 'withdraw/cancel', - 'transaction/status', // see 'history/transactions' in private tapi above - ], - }, - }, - 'exceptions': { - 'exact': { - 'Sign is invalid': AuthenticationError, // {"success":0,"error":"Sign is invalid"} - 'Order was rejected. Incorrect price.': InvalidOrder, // {"success":0,"error":"Order was rejected. Incorrect price."} - "Order was rejected. You don't have enough money.": InsufficientFunds, // {"success":0,"error":"Order was rejected. You don't have enough money."} - 'This method is blocked for your pair of keys': PermissionDenied, // {"success":0,"error":"This method is blocked for your pair of keys"} - }, - 'broad': { - 'INVALID_PARAMETER': BadRequest, - 'Invalid pair name': ExchangeError, // {"success":0,"error":"Invalid pair name: btc_eth"} - 'invalid api key': AuthenticationError, - 'invalid sign': AuthenticationError, - 'api key dont have trade permission': AuthenticationError, - 'invalid parameter': InvalidOrder, - 'invalid order': InvalidOrder, - 'Requests too often': DDoSProtection, - 'not available': ExchangeNotAvailable, - 'data unavailable': ExchangeNotAvailable, - 'external service unavailable': ExchangeNotAvailable, - 'nonce is invalid': InvalidNonce, // {"success":0,"error":"Parameter: nonce is invalid"} - 'Incorrect volume': InvalidOrder, // {"success": 0,"error":"Order was rejected. Incorrect volume."} - }, - }, - 'options': { - 'fetchTickersMaxLength': 250, - }, - 'commonCurrencies': { - 'DSH': 'DASH', - }, - }); - } - - async fetchMarkets (params = {}) { - const response = await this.publicGetInfo (params); - // - // { - // "server_time": 1522057909, - // "pairs": { - // "ethusd": { - // "decimal_places": 5, - // "min_price": 100, - // "max_price": 1500, - // "min_amount": 0.01, - // "hidden": 0, - // "fee": 0, - // "amount_decimal_places": 4, - // "quoted_currency": "USD", - // "base_currency": "ETH" - // } - // } - // } - // - const markets = this.safeValue (response, 'pairs'); - const keys = Object.keys (markets); - const result = []; - for (let i = 0; i < keys.length; i++) { - const id = keys[i]; - const market = markets[id]; - const baseId = this.safeString (market, 'base_currency'); - const quoteId = this.safeString (market, 'quoted_currency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const precision = { - 'amount': this.safeInteger (market, 'decimal_places'), - 'price': this.safeInteger (market, 'decimal_places'), - }; - const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), - }; - const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), - }; - const costLimits = { - 'min': this.safeFloat (market, 'min_total'), - }; - const limits = { - 'amount': amountLimits, - 'price': priceLimits, - 'cost': costLimits, - }; - const hidden = this.safeInteger (market, 'hidden'); - const active = (hidden === 0); - // see parseMarket below - // https://github.com/ccxt/ccxt/pull/5786 - const otherId = base.toLowerCase () + quote.toLowerCase (); - result.push ({ - 'id': id, - 'otherId': otherId, // https://github.com/ccxt/ccxt/pull/5786 - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': active, - 'precision': precision, - 'limits': limits, - 'info': market, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostInfoAccount (); - // - // { - // "success" : 1, - // "return" : { - // "funds" : { - // "BTC" : { - // "total" : 0, - // "available" : 0 - // }, - // "USD" : { - // "total" : 0, - // "available" : 0 - // }, - // "USDT" : { - // "total" : 0, - // "available" : 0 - // } - // }, - // "rights" : { - // "info" : 1, - // "trade" : 1 - // }, - // "transactionCount" : 0, - // "openOrders" : 0, - // "serverTime" : 1537451465 - // } - // } - // - const balances = this.safeValue (response, 'return'); - const result = { 'info': response }; - const funds = this.safeValue (balances, 'funds'); - const currencyIds = Object.keys (funds); - for (let i = 0; i < currencyIds.length; i++) { - const currencyId = currencyIds[i]; - const code = this.safeCurrencyCode (currencyId); - const balance = this.safeValue (funds, currencyId, {}); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseTicker (ticker, market = undefined) { - // - // { high: 0.03492, - // low: 0.03245, - // avg: 29.46133, - // vol: 500.8661, - // vol_cur: 17.000797104, - // last: 0.03364, - // buy: 0.03362, - // sell: 0.03381, - // updated: 1537521993, - // pair: "ethbtc" } - // - const timestamp = this.safeTimestamp (ticker, 'updated'); - let symbol = undefined; - const marketId = this.safeString (ticker, 'pair'); - market = this.parseMarket (marketId); - if (market !== undefined) { - symbol = market['symbol']; - } - // dsx average is inverted, liqui average is not - let average = this.safeFloat (ticker, 'avg'); - if (average !== undefined) { - if (average > 0) { - average = 1 / average; - } - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_cur'), - 'info': ticker, - }; - } - - parseTrade (trade, market = undefined) { - // - // fetchTrades (public) - // - // { - // "amount" : 0.0128, - // "price" : 6483.99000, - // "timestamp" : 1540334614, - // "tid" : 35684364, - // "type" : "ask" - // } - // - // fetchMyTrades (private) - // - // { - // "number": "36635882", // <-- this is present if the trade has come from the '/order/status' call - // "id": "36635882", // <-- this may have been artifically added by the parseTrades method - // "pair": "btcusd", - // "type": "buy", - // "volume": 0.0595, - // "rate": 9750, - // "orderId": 77149299, - // "timestamp": 1519612317, - // "commission": 0.00020825, - // "commissionCurrency": "btc" - // } - // - const timestamp = this.safeTimestamp (trade, 'timestamp'); - let side = this.safeString (trade, 'type'); - if (side === 'ask') { - side = 'sell'; - } else if (side === 'bid') { - side = 'buy'; - } - const price = this.safeFloat2 (trade, 'rate', 'price'); - const id = this.safeString2 (trade, 'number', 'id'); - const orderId = this.safeString (trade, 'orderId'); - const marketId = this.safeString (trade, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const amount = this.safeFloat2 (trade, 'amount', 'volume'); - const type = 'limit'; // all trades are still limit trades - let takerOrMaker = undefined; - let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const isYourOrder = this.safeValue (trade, 'is_your_order'); - if (isYourOrder !== undefined) { - takerOrMaker = 'taker'; - if (isYourOrder) { - takerOrMaker = 'maker'; - } - if (fee === undefined) { - fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); - } - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - return { - 'id': id, - 'order': orderId, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': type, - 'side': side, - 'takerOrMaker': takerOrMaker, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - 'info': trade, - }; - } - - parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - let result = []; - if (Array.isArray (trades)) { - for (let i = 0; i < trades.length; i++) { - result.push (this.parseTrade (trades[i], market)); - } - } else { - const ids = Object.keys (trades); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const trade = this.parseTrade (trades[id], market); - result.push (this.extend (trade, { 'id': id }, params)); - } - } - result = this.sortBy (result, 'timestamp'); - const symbol = (market !== undefined) ? market['symbol'] : undefined; - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const market_id_in_reponse = (market['id'] in response); - if (!market_id_in_reponse) { - throw new ExchangeError (this.id + ' ' + market['symbol'] + ' order book is empty or not available'); - } - const orderbook = response[market['id']]; - return this.parseOrderBook (orderbook); - } - - async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let ids = undefined; - if (symbols === undefined) { - ids = this.ids.join ('-'); - // max URL length is 2083 symbols, including http schema, hostname, tld, etc... - if (ids.length > 2048) { - const numIds = this.ids.length; - throw new ExchangeError (this.id + ' has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const result = {}; - ids = Object.keys (response); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let symbol = id; - if (id in this.markets_by_id) { - const market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseOrderBook (response[id]); - } - return result; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - let ids = this.ids; - if (symbols === undefined) { - const numIds = ids.length; - ids = ids.join ('-'); - const maxLength = this.safeInteger (this.options, 'fetchTickersMaxLength', 2048); - // max URL length is 2048 symbols, including http schema, hostname, tld, etc... - if (ids.length > this.options['fetchTickersMaxLength']) { - throw new ArgumentsRequired (this.id + ' has ' + numIds.toString () + ' markets exceeding max URL length for this endpoint (' + maxLength.toString () + ' characters), please, specify a list of symbols of interest in the first argument to fetchTickers'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - const tickers = await this.publicGetTickerPair (this.extend (request, params)); - // - // { - // "bchbtc" : { - // "high" : 0.02989, - // "low" : 0.02736, - // "avg" : 33.90585, - // "vol" : 0.65982205, - // "vol_cur" : 0.0194604180960, - // "last" : 0.03000, - // "buy" : 0.02980, - // "sell" : 0.03001, - // "updated" : 1568104614, - // "pair" : "bchbtc" - // }, - // "ethbtc" : { - // "high" : 0.01772, - // "low" : 0.01742, - // "avg" : 56.89082, - // "vol" : 229.247115044, - // "vol_cur" : 4.02959737298943, - // "last" : 0.01769, - // "buy" : 0.01768, - // "sell" : 0.01776, - // "updated" : 1568104614, - // "pair" : "ethbtc" - // } - // } - // - const result = {}; - const keys = Object.keys (tickers); - for (let k = 0; k < keys.length; k++) { - const id = keys[k]; - const ticker = tickers[id]; - let symbol = id; - let market = undefined; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseTicker (ticker, market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - const tickers = await this.fetchTickers ([ symbol ], params); - return tickers[symbol]; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; - } - const response = await this.publicGetTradesPair (this.extend (request, params)); - if (Array.isArray (response)) { - const numElements = response.length; - if (numElements === 0) { - return []; - } - } - return this.parseTrades (response[market['id']], market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // } - // - return [ - this.safeInteger (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - 'period': this.timeframes[timeframe], - }; - let method = 'publicGetLastBarsPairPeriodAmount'; - if (since === undefined) { - if (limit === undefined) { - limit = 100; // required, max 2000 - } - request['amount'] = limit; - } else { - method = 'publicGetPeriodBarsPairPeriodStartEnd'; - // in their docs they expect milliseconds - // but it returns empty arrays with milliseconds - // however, it does work properly with seconds - request['start'] = parseInt (since / 1000); - if (limit === undefined) { - request['end'] = this.seconds (); - } else { - const duration = this.parseTimeframe (timeframe) * 1000; - const end = this.sum (since, duration * limit); - request['end'] = parseInt (end / 1000); - } - } - const response = await this[method] (this.extend (request, params)); - // - // { - // "ethbtc": [ - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // }, - // { - // "high" : 0.01967, - // "open" : 0.01967, - // "low" : 0.01967, - // "close" : 0.01967, - // "amount" : 0, - // "timestamp" : 1565155680000 - // } - // ] - // } - // - const candles = this.safeValue (response, market['id'], []); - return this.parseOHLCVs (candles, market, timeframe, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (type === 'market' && price === undefined) { - throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument even for market orders, that is the worst price that you agree to fill your order for'); - } - const request = { - 'pair': market['id'], - 'type': side, - 'volume': this.amountToPrecision (symbol, amount), - 'rate': this.priceToPrecision (symbol, price), - 'orderType': type, - }; - price = parseFloat (price); - amount = parseFloat (amount); - const response = await this.privatePostOrderNew (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "received": 0, - // "remains": 10, - // "funds": { - // "BTC": { - // "total": 100, - // "available": 95 - // }, - // "USD": { - // "total": 10000, - // "available": 9995 - // }, - // "EUR": { - // "total": 1000, - // "available": 995 - // }, - // "LTC": { - // "total": 1000, - // "available": 995 - // } - // }, - // "orderId": 0, // https://github.com/ccxt/ccxt/issues/3677 - // } - // } - // - let status = 'open'; - let filled = 0.0; - let remaining = amount; - const responseReturn = this.safeValue (response, 'return'); - let id = this.safeString2 (responseReturn, 'orderId', 'order_id'); - if (id === '0') { - id = this.safeString (responseReturn, 'initOrderId', 'init_order_id'); - status = 'closed'; - } - filled = this.safeFloat (responseReturn, 'received', 0.0); - remaining = this.safeFloat (responseReturn, 'remains', amount); - const timestamp = this.milliseconds (); - return { - 'info': response, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'side': side, - 'price': price, - 'cost': price * filled, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'fee': undefined, - // 'trades': this.parseTrades (order['trades'], market), - }; - } - - parseOrderStatus (status) { - const statuses = { - '0': 'open', // Active - '1': 'closed', // Filled - '2': 'canceled', // Killed - '3': 'canceling', // Killing - '7': 'canceled', // Rejected - }; - return this.safeString (statuses, status, status); - } - - parseMarket (id) { - if (id in this.markets_by_id) { - return this.markets_by_id[id]; - } else { - // the following is a fix for - // https://github.com/ccxt/ccxt/pull/5786 - // https://github.com/ccxt/ccxt/issues/5770 - let markets_by_other_id = this.safeValue (this.options, 'markets_by_other_id'); - if (markets_by_other_id === undefined) { - this.options['markets_by_other_id'] = this.indexBy (this.markets, 'otherId'); - markets_by_other_id = this.options['markets_by_other_id']; - } - if (id in markets_by_other_id) { - return markets_by_other_id[id]; - } - } - return undefined; - } - - parseOrder (order, market = undefined) { - // - // fetchOrder - // - // { - // "number": 36635882, - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // - const id = this.safeString (order, 'id'); - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const timestamp = this.safeTimestamp (order, 'timestampCreated'); - const marketId = this.safeString (order, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const remaining = this.safeFloat (order, 'remainingVolume'); - const amount = this.safeFloat (order, 'volume'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } - } - const orderType = this.safeString (order, 'orderType'); - const side = this.safeString (order, 'type'); - let fee = undefined; - const deals = this.safeValue (order, 'deals', []); - const numDeals = deals.length; - let trades = undefined; - let lastTradeTimestamp = undefined; - if (numDeals > 0) { - trades = this.parseTrades (deals); - let feeCost = undefined; - let feeCurrency = undefined; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - if (feeCost === undefined) { - feeCost = 0; - } - feeCost = this.sum (feeCost, trade['fee']['cost']); - feeCurrency = trade['fee']['currency']; - lastTradeTimestamp = trade['timestamp']; - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'type': orderType, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': undefined, - 'cost': cost, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'status': status, - 'fee': fee, - 'trades': trades, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': parseInt (id), - }; - const response = await this.privatePostOrderStatus (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // } - // - return this.parseOrder (this.extend ({ - 'id': id, - }, response['return'])); - } - - parseOrdersById (orders, symbol = undefined, since = undefined, limit = undefined) { - const ids = Object.keys (orders); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.parseOrder (this.extend ({ - 'id': id.toString (), - }, orders[id])); - result.push (order); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - const response = await this.privatePostOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': id, - }; - const response = await this.privatePostOrderCancel (this.extend (request, params)); - return response; - } - - parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { - const result = []; - const ids = Object.keys (orders); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.extend ({ 'id': id }, orders[id]); - result.push (this.extend (this.parseOrder (order, market), params)); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - const orders = await this.fetchOrders (symbol, since, limit, params); - return this.filterBy (orders, 'status', 'closed'); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let market = undefined; - // some derived classes use camelcase notation for request fields - const request = { - // 'from': 123456789, // trade ID, from which the display starts numerical 0 (test result: liqui ignores this field) - // 'count': 1000, // the number of trades for display numerical, default = 1000 - // 'from_id': trade ID, from which the display starts numerical 0 - // 'end_id': trade ID on which the display ends numerical ∞ - // 'order': 'ASC', // sorting, default = DESC (test result: liqui ignores this field, most recent trade always goes last) - // 'since': 1234567890, // UTC start time, default = 0 (test result: liqui ignores this field) - // 'end': 1234567890, // UTC end time, default = ∞ (test result: liqui ignores this field) - // 'pair': 'eth_btc', // default = all markets - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['pair'] = market['id']; - } - if (limit !== undefined) { - request['count'] = parseInt (limit); - } - if (since !== undefined) { - request['since'] = parseInt (since / 1000); - } - const response = await this.privatePostHistoryTrades (this.extend (request, params)); - let trades = []; - if ('return' in response) { - trades = response['return']; - } - return this.parseTrades (trades, market, since, limit); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let currency = undefined; - const request = {}; - if (code !== undefined) { - currency = this.currency (code); - request['currency'] = currency['id']; - } - if (since !== undefined) { - request['since'] = since; - } - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryTransactions (this.extend (request, params)); - // - // { - // "success": 1, - // "return": [ - // { - // "id": 1, - // "timestamp": 11, - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // ] - // } - // - const transactions = this.safeValue (response, 'return', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - '1': 'failed', - '2': 'ok', - '3': 'pending', - '4': 'failed', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // "id": 1, - // "timestamp": 11, // 11 in their docs ( - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // - const timestamp = this.safeTimestamp (transaction, 'timestamp'); - let type = this.safeString (transaction, 'type'); - if (type !== undefined) { - if (type === 'Incoming') { - type = 'deposit'; - } else if (type === 'Withdraw') { - type = 'withdrawal'; - } - } - const currencyId = this.safeString (transaction, 'currency'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - return { - 'id': this.safeString (transaction, 'id'), - 'txid': this.safeString (transaction, 'txid'), - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'address': this.safeString (transaction, 'address'), - 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), - 'currency': code, - 'status': status, - 'fee': { - 'currency': code, - 'cost': this.safeFloat (transaction, 'commission'), - 'rate': undefined, - }, - 'info': transaction, - }; - } - - async createDepositAddress (code, params = {}) { - const request = { - 'new': 1, - }; - const response = await this.fetchDepositAddress (code, this.extend (request, params)); - return response; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency': currency['id'], - }; - const response = await this.dwapiPostDepositCryptoaddress (this.extend (request, params)); - const result = this.safeValue (response, 'return', {}); - const address = this.safeString (result, 'address'); - this.checkAddress (address); - return { - 'currency': code, - 'address': address, - 'tag': undefined, // not documented in DSX API - 'info': response, - }; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - const commission = this.safeValue (params, 'commission'); - if (commission === undefined) { - throw new ArgumentsRequired (this.id + ' withdraw() requires a `commission` (withdrawal fee) parameter (string)'); - } - params = this.omit (params, commission); - const request = { - 'currency': currency['id'], - 'amount': parseFloat (amount), - 'address': address, - 'commission': commission, - }; - if (tag !== undefined) { - request['address'] += ':' + tag; - } - const response = await this.dwapiPostWithdrawCrypto (this.extend (request, params)); - // - // [ - // { - // "success": 1, - // "return": { - // "transactionId": 2863073 - // } - // } - // ] - // - const data = this.safeValue (response, 'return', {}); - const id = this.safeString (data, 'transactionId'); - return { - 'info': response, - 'id': id, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'][api]; - const query = this.omit (params, this.extractParams (path)); - if (api === 'private' || api === 'dwapi') { - url += '/' + this.version + '/' + this.implodeParams (path, params); - this.checkRequiredCredentials (); - const nonce = this.nonce (); - body = this.urlencode (this.extend ({ - 'nonce': nonce, - }, query)); - const signature = this.hmac (this.encode (body), this.encode (this.secret), 'sha512', 'base64'); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': signature, - }; - } else if (api === 'public') { - url += '/' + this.implodeParams (path, params); - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - url += '/' + this.implodeParams (path, params); - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - if (Object.keys (query).length) { - body = this.json (query); - headers = { - 'Content-Type': 'application/json', - }; - } - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - if ('success' in response) { - // - // 1 - Liqui only returns the integer 'success' key from their private API - // - // { "success": 1, ... } httpCode === 200 - // { "success": 0, ... } httpCode === 200 - // - // 2 - However, exchanges derived from Liqui, can return non-integers - // - // It can be a numeric string - // { "sucesss": "1", ... } - // { "sucesss": "0", ... }, httpCode >= 200 (can be 403, 502, etc) - // - // Or just a string - // { "success": "true", ... } - // { "success": "false", ... }, httpCode >= 200 - // - // Or a boolean - // { "success": true, ... } - // { "success": false, ... }, httpCode >= 200 - // - // 3 - Oversimplified, Python PEP8 forbids comparison operator (===) of different types - // - // 4 - We do not want to copy-paste and duplicate the code of this handler to other exchanges derived from Liqui - // - // To cover points 1, 2, 3 and 4 combined this handler should work like this: - // - let success = this.safeValue (response, 'success', false); - if (typeof success === 'string') { - if ((success === 'true') || (success === '1')) { - success = true; - } else { - success = false; - } - } - if (!success) { - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'error'); - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/equos.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/equos.js index 5dc44a2ac..0b90d79ed 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/equos.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/equos.js @@ -221,7 +221,7 @@ module.exports = class equos extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeVol'), + 'min': this.safeNumber (market, 'minTradeVol'), 'max': undefined, }, 'price': { @@ -287,7 +287,7 @@ module.exports = class equos extends Exchange { const name = this.safeString (currency, 6); const status = this.safeInteger (currency, 4); const active = (status === 1); - const fee = this.safeFloat (currency, 5); // withdraw_fee + const fee = this.safeNumber (currency, 5); // withdraw_fee return { 'id': id, 'info': currency, @@ -379,8 +379,8 @@ module.exports = class equos extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); return [ this.convertFromScale (price, market['precision']['price']), this.convertFromScale (amount, market['precision']['amount']), @@ -526,9 +526,9 @@ module.exports = class equos extends Exchange { orderId = this.safeString (trade, 'orderId'); side = this.safeStringLower (trade, 'side'); type = this.parseOrderType (this.safeString (trade, 'ordType')); - price = this.safeFloat (trade, 'lastPx'); - amount = this.safeFloat (trade, 'quoteQty'); - let feeCost = this.safeFloat (trade, 'commission'); + price = this.safeNumber (trade, 'lastPx'); + amount = this.safeNumber (trade, 'quoteQty'); + let feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { feeCost = -feeCost; const feeCurrencyId = this.safeString (trade, 'commCurrency'); @@ -599,8 +599,8 @@ module.exports = class equos extends Exchange { if (assetType === 'ASSET') { const currencyId = this.safeString (position, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const quantity = this.safeFloat (position, 'quantity'); - const availableQuantity = this.safeFloat (position, 'availableQuantity'); + const quantity = this.safeNumber (position, 'quantity'); + const availableQuantity = this.safeNumber (position, 'availableQuantity'); const scale = this.safeInteger (position, 'quantity_scale'); const account = this.account (); account['free'] = this.convertFromScale (availableQuantity, scale); @@ -646,7 +646,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -743,7 +743,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -1116,7 +1116,7 @@ module.exports = class equos extends Exchange { address = undefined; } const type = this.safeString (transaction, 'type'); - let amount = this.safeFloat (transaction, 'balance_change'); + let amount = this.safeNumber (transaction, 'balance_change'); if (amount === undefined) { amount = this.safeInteger (transaction, 'quantity'); const amountScale = this.safeInteger (transaction, 'quantity_scale'); @@ -1199,8 +1199,8 @@ module.exports = class equos extends Exchange { for (let i = 0; i < tradingFees.length; i++) { const tradingFee = tradingFees[i]; if (this.safeString (tradingFee, 'tier') !== undefined) { - taker[tradingFee['tier']] = this.safeFloat (tradingFee, 'taker'); - maker[tradingFee['tier']] = this.safeFloat (tradingFee, 'maker'); + taker[tradingFee['tier']] = this.safeNumber (tradingFee, 'taker'); + maker[tradingFee['tier']] = this.safeNumber (tradingFee, 'maker'); } } return { @@ -1331,28 +1331,6 @@ module.exports = class equos extends Exchange { let remaining = this.safeInteger (order, 'leavesQty'); const remainingScale = this.safeInteger (order, 'leavesQty_scale'); remaining = this.convertFromScale (remaining, remainingScale); - if (remaining <= 0) { - if ((filled !== undefined) && (amount !== undefined) && (filled < amount)) { - remaining = undefined; - } - } - if ((remaining === undefined) && (amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0); - } - let average = this.safeInteger (order, 'price', 0); - if (average === 0) { - average = undefined; - } - const averageScale = this.safeInteger (order, 'price_scale'); - average = this.convertFromScale (average, averageScale); - let cost = undefined; - if (filled !== 0) { - if (average > 0) { - cost = average * filled; - } else if (price > 0) { - cost = price * filled; - } - } let fee = undefined; const currencyId = this.safeInteger (order, 'feeInstrumentId'); const feeCurrencyCode = this.safeCurrencyCode (currencyId); @@ -1375,7 +1353,7 @@ module.exports = class equos extends Exchange { } const stopPriceScale = this.safeInteger (order, 'stopPx_scale', 0); const stopPrice = this.convertFromScale (this.safeInteger (order, 'stopPx'), stopPriceScale); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1390,14 +1368,14 @@ module.exports = class equos extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/eterbase.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/eterbase.js index 40d2893d3..531327d1d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/eterbase.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/eterbase.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, InvalidOrder, ExchangeError, BadRequest, BadSymbol } = require ('./base/errors'); const { TRUNCATE, SIGNIFICANT_DIGITS } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -217,7 +218,7 @@ module.exports = class eterbase extends Exchange { const rule = rules[i]; const attribute = this.safeString (rule, 'attribute'); const condition = this.safeString (rule, 'condition'); - const value = this.safeFloat (rule, 'value'); + const value = this.safeNumber (rule, 'value'); if ((attribute === 'Qty') && (condition === 'Min')) { minAmount = value; } else if ((attribute === 'Qty') && (condition === 'Max')) { @@ -307,7 +308,7 @@ module.exports = class eterbase extends Exchange { 'type': type, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -323,8 +324,8 @@ module.exports = class eterbase extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMin'), - 'max': this.safeFloat (currency, 'withdrawalMax'), + 'min': this.safeNumber (currency, 'withdrawalMin'), + 'max': this.safeNumber (currency, 'withdrawalMax'), }, }, }; @@ -351,17 +352,17 @@ module.exports = class eterbase extends Exchange { const marketId = this.safeString (ticker, 'marketId'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const last = this.safeFloat (ticker, 'price'); - const baseVolume = this.safeFloat (ticker, 'volumeBase'); - const quoteVolume = this.safeFloat (ticker, 'volume'); + const last = this.safeNumber (ticker, 'price'); + const baseVolume = this.safeNumber (ticker, 'volumeBase'); + const quoteVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const percentage = this.safeFloat (ticker, 'change'); + const percentage = this.safeNumber (ticker, 'change'); const result = { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -403,14 +404,6 @@ module.exports = class eterbase extends Exchange { return this.parseTicker (response, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { @@ -465,10 +458,12 @@ module.exports = class eterbase extends Exchange { // "filledAt": 1556355722341 // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -477,9 +472,9 @@ module.exports = class eterbase extends Exchange { 'currency': feeCurrencyCode, }; } - let cost = this.safeFloat (trade, 'qty'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + let cost = this.safeNumber (trade, 'qty'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger2 (trade, 'executedAt', 'filledAt'); const tradeSide = this.safeString (trade, 'side'); @@ -577,11 +572,11 @@ module.exports = class eterbase extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -644,14 +639,13 @@ module.exports = class eterbase extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetId'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'reserved'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -778,18 +772,18 @@ module.exports = class eterbase extends Exchange { } else { type = 'stoplimit'; } - let price = this.safeFloat (order, 'limitPrice'); - const amount = this.safeFloat (order, 'qty'); - let remaining = this.safeFloat (order, 'remainingQty'); + let price = this.safeNumber (order, 'limitPrice'); + const amount = this.safeNumber (order, 'qty'); + let remaining = this.safeNumber (order, 'remainingQty'); let filled = undefined; - const remainingCost = this.safeFloat (order, 'remainingCost'); + const remainingCost = this.safeNumber (order, 'remainingCost'); if ((remainingCost !== undefined) && (remainingCost === 0.0)) { remaining = 0; } if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); } - const cost = this.safeFloat (order, 'cost'); + const cost = this.safeNumber (order, 'cost'); if (type === 'market') { if (price === 0.0) { if ((cost !== undefined) && (filled !== undefined)) { @@ -806,7 +800,7 @@ module.exports = class eterbase extends Exchange { } } const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -979,7 +973,7 @@ module.exports = class eterbase extends Exchange { } if ((uppercaseType === 'MARKET') && (uppercaseSide === 'BUY')) { // for market buy it requires the amount of quote currency to spend - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); if (this.options['createMarketBuyOrderRequiresPrice']) { if (cost === undefined) { if (price !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exmo.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exmo.js index c9e19479d..d79e42079 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exmo.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exmo.js @@ -112,6 +112,7 @@ module.exports = class exmo extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.2 / 100, @@ -581,18 +582,18 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = marketId.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const maxAmount = this.safeFloat (limit, 'max_q'); - const maxPrice = this.safeFloat (limit, 'max_p'); - const maxCost = this.safeFloat (limit, 'max_a'); - const minAmount = this.safeFloat (limit, 'min_q'); - const minPrice = this.safeFloat (limit, 'min_p'); - const minCost = this.safeFloat (limit, 'min_a'); - minAmounts[base] = Math.min (this.safeFloat (minAmounts, base, minAmount), minAmount); - maxAmounts[base] = Math.max (this.safeFloat (maxAmounts, base, maxAmount), maxAmount); - minPrices[quote] = Math.min (this.safeFloat (minPrices, quote, minPrice), minPrice); - minCosts[quote] = Math.min (this.safeFloat (minCosts, quote, minCost), minCost); - maxPrices[quote] = Math.max (this.safeFloat (maxPrices, quote, maxPrice), maxPrice); - maxCosts[quote] = Math.max (this.safeFloat (maxCosts, quote, maxCost), maxCost); + const maxAmount = this.safeNumber (limit, 'max_q'); + const maxPrice = this.safeNumber (limit, 'max_p'); + const maxCost = this.safeNumber (limit, 'max_a'); + const minAmount = this.safeNumber (limit, 'min_q'); + const minPrice = this.safeNumber (limit, 'min_p'); + const minCost = this.safeNumber (limit, 'min_a'); + minAmounts[base] = Math.min (this.safeNumber (minAmounts, base, minAmount), minAmount); + maxAmounts[base] = Math.max (this.safeNumber (maxAmounts, base, maxAmount), maxAmount); + minPrices[quote] = Math.min (this.safeNumber (minPrices, quote, minPrice), minPrice); + minCosts[quote] = Math.min (this.safeNumber (minCosts, quote, minCost), minCost); + maxPrices[quote] = Math.max (this.safeNumber (maxPrices, quote, maxPrice), maxPrice); + maxCosts[quote] = Math.max (this.safeNumber (maxCosts, quote, maxCost), maxCost); } const result = {}; for (let i = 0; i < ids.length; i++) { @@ -609,16 +610,16 @@ module.exports = class exmo extends Exchange { 'precision': 8, 'limits': { 'amount': { - 'min': this.safeFloat (minAmounts, code), - 'max': this.safeFloat (maxAmounts, code), + 'min': this.safeNumber (minAmounts, code), + 'max': this.safeNumber (maxAmounts, code), }, 'price': { - 'min': this.safeFloat (minPrices, code), - 'max': this.safeFloat (maxPrices, code), + 'min': this.safeNumber (minPrices, code), + 'max': this.safeNumber (maxPrices, code), }, 'cost': { - 'min': this.safeFloat (minCosts, code), - 'max': this.safeFloat (maxCosts, code), + 'min': this.safeNumber (minCosts, code), + 'max': this.safeNumber (maxCosts, code), }, }, 'info': id, @@ -653,8 +654,8 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = symbol.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const taker = this.safeFloat (market, 'commission_taker_percent'); - const maker = this.safeFloat (market, 'commission_maker_percent'); + const taker = this.safeNumber (market, 'commission_taker_percent'); + const maker = this.safeNumber (market, 'commission_maker_percent'); result.push ({ 'id': id, 'symbol': symbol, @@ -667,16 +668,16 @@ module.exports = class exmo extends Exchange { 'maker': maker / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, }, 'precision': { @@ -749,11 +750,11 @@ module.exports = class exmo extends Exchange { // return [ this.safeInteger (ohlcv, 't'), - this.safeFloat (ohlcv, 'o'), - this.safeFloat (ohlcv, 'h'), - this.safeFloat (ohlcv, 'l'), - this.safeFloat (ohlcv, 'c'), - this.safeFloat (ohlcv, 'v'), + this.safeNumber (ohlcv, 'o'), + this.safeNumber (ohlcv, 'h'), + this.safeNumber (ohlcv, 'l'), + this.safeNumber (ohlcv, 'c'), + this.safeNumber (ohlcv, 'v'), ]; } @@ -769,14 +770,14 @@ module.exports = class exmo extends Exchange { const currencyId = this.currencyId (code); const account = this.account (); if (currencyId in free) { - account['free'] = this.safeFloat (free, currencyId); + account['free'] = this.safeString (free, currencyId); } if (currencyId in used) { - account['used'] = this.safeFloat (used, currencyId); + account['used'] = this.safeString (used, currencyId); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -834,16 +835,16 @@ module.exports = class exmo extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -852,9 +853,9 @@ module.exports = class exmo extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_curr'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'vol_curr'), 'info': ticker, }; } @@ -915,9 +916,9 @@ module.exports = class exmo extends Exchange { let symbol = undefined; const id = this.safeString (trade, 'trade_id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'quantity'); + const cost = this.safeNumber (trade, 'amount'); const side = this.safeString (trade, 'type'); const type = undefined; const marketId = this.safeString (trade, 'pair'); @@ -936,11 +937,11 @@ module.exports = class exmo extends Exchange { } const takerOrMaker = this.safeString (trade, 'exec_type'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission_amount'); + const feeCost = this.safeNumber (trade, 'commission_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commission_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (trade, 'commission_percent'); + let feeRate = this.safeNumber (trade, 'commission_percent'); if (feeRate !== undefined) { feeRate /= 1000; } @@ -1239,13 +1240,13 @@ module.exports = class exmo extends Exchange { market = this.markets_by_id[marketId]; } } - let amount = this.safeFloat (order, 'quantity'); + let amount = this.safeNumber (order, 'quantity'); if (amount === undefined) { const amountField = (side === 'buy') ? 'in_amount' : 'out_amount'; - amount = this.safeFloat (order, amountField); + amount = this.safeNumber (order, amountField); } - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'amount'); + let price = this.safeNumber (order, 'price'); + let cost = this.safeNumber (order, 'amount'); let filled = 0.0; const trades = []; const transactions = this.safeValue (order, 'trades', []); @@ -1366,24 +1367,6 @@ module.exports = class exmo extends Exchange { return undefined; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -1428,7 +1411,7 @@ module.exports = class exmo extends Exchange { // } // const timestamp = this.safeTimestamp (transaction, 'dt'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -1458,7 +1441,7 @@ module.exports = class exmo extends Exchange { // fixed funding fees only (for now) if (!this.fees['funding']['percentage']) { const key = (type === 'withdrawal') ? 'withdraw' : 'deposit'; - let feeCost = this.safeFloat (this.options['fundingFees'][key], code); + let feeCost = this.safeNumber (this.options['fundingFees'][key], code); // users don't pay for cashbacks, no fees for that const provider = this.safeString (transaction, 'provider'); if (provider === 'cashback') { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exx.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exx.js index c4c12d03f..72b59ef1b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exx.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/exx.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ExchangeNotAvailable, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -148,26 +149,26 @@ module.exports = class exx extends Exchange { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); ticker = ticker['ticker']; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'riseRate'), + 'change': this.safeNumber (ticker, 'riseRate'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -217,14 +218,11 @@ module.exports = class exx extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -269,14 +267,13 @@ module.exports = class exx extends Exchange { const currencyId = currencies[i]; const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'balance'), - 'used': this.safeFloat (balance, 'freeze'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -296,11 +293,10 @@ module.exports = class exx extends Exchange { // const symbol = market['symbol']; const timestamp = parseInt (order['trade_date']); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'trade_money'); - const amount = this.safeFloat (order, 'total_amount'); - const filled = this.safeFloat (order, 'trade_amount', 0.0); - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'trade_money'); + const amount = this.safeNumber (order, 'total_amount'); + const filled = this.safeNumber (order, 'trade_amount', 0.0); let status = this.safeInteger (order, 'status'); if (status === 1) { status = 'canceled'; @@ -312,11 +308,11 @@ module.exports = class exx extends Exchange { let fee = undefined; if ('fees' in order) { fee = { - 'cost': this.safeFloat (order, 'fees'), + 'cost': this.safeNumber (order, 'fees'), 'currency': market['quote'], }; } - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -333,12 +329,12 @@ module.exports = class exx extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/fcoin.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/fcoin.js index 2d1c845ab..2d90e7cce 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/fcoin.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/fcoin.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, ArgumentsRequired, InsufficientFunds, InvalidOrder, RateLimitExceeded, InvalidNonce, AuthenticationError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -223,8 +224,8 @@ module.exports = class fcoin extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'limit_amount_min'), - 'max': this.safeFloat (market, 'limit_amount_max'), + 'min': this.safeNumber (market, 'limit_amount_min'), + 'max': this.safeNumber (market, 'limit_amount_max'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -319,12 +320,12 @@ module.exports = class fcoin extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidsAsks (orders, priceKey = 0, amountKey = 1) { @@ -337,8 +338,8 @@ module.exports = class fcoin extends Exchange { const priceField = this.sum (index, priceKey); const amountField = this.sum (index, amountKey); result.push ([ - this.safeFloat (orders, priceField), - this.safeFloat (orders, amountField), + this.safeNumber (orders, priceField), + this.safeNumber (orders, amountField), ]); } return result; @@ -386,17 +387,17 @@ module.exports = class fcoin extends Exchange { } } const values = ticker['ticker']; - const last = this.safeFloat (values, 0); + const last = this.safeNumber (values, 0); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (values, 7), - 'low': this.safeFloat (values, 8), - 'bid': this.safeFloat (values, 2), - 'bidVolume': this.safeFloat (values, 3), - 'ask': this.safeFloat (values, 4), - 'askVolume': this.safeFloat (values, 5), + 'high': this.safeNumber (values, 7), + 'low': this.safeNumber (values, 8), + 'bid': this.safeNumber (values, 2), + 'bidVolume': this.safeNumber (values, 3), + 'ask': this.safeNumber (values, 4), + 'askVolume': this.safeNumber (values, 5), 'vwap': undefined, 'open': undefined, 'close': last, @@ -405,8 +406,8 @@ module.exports = class fcoin extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (values, 9), - 'quoteVolume': this.safeFloat (values, 10), + 'baseVolume': this.safeNumber (values, 9), + 'quoteVolume': this.safeNumber (values, 10), 'info': ticker, }; } @@ -419,14 +420,11 @@ module.exports = class fcoin extends Exchange { const timestamp = this.safeInteger (trade, 'ts'); const side = this.safeStringLower (trade, 'side'); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = undefined; return { 'id': id, @@ -551,38 +549,25 @@ module.exports = class fcoin extends Exchange { const symbol = market['symbol']; const orderType = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'created_at'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'executed_value'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'executed_value'); let feeCurrency = undefined; let feeCost = undefined; - const feeRebate = this.safeFloat (order, 'fees_income'); + const feeRebate = this.safeNumber (order, 'fees_income'); if ((feeRebate !== undefined) && (feeRebate > 0)) { if (market !== undefined) { feeCurrency = (side === 'buy') ? market['quote'] : market['base']; } feeCost = -feeRebate; } else { - feeCost = this.safeFloat (order, 'fill_fees'); + feeCost = this.safeNumber (order, 'fill_fees'); if (market !== undefined) { feeCurrency = (side === 'buy') ? market['base'] : market['quote']; } } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -598,7 +583,7 @@ module.exports = class fcoin extends Exchange { 'stopPrice': undefined, 'cost': cost, 'amount': amount, - 'remaining': remaining, + 'remaining': undefined, 'filled': filled, 'average': undefined, 'status': status, @@ -607,7 +592,7 @@ module.exports = class fcoin extends Exchange { 'currency': feeCurrency, }, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -649,11 +634,11 @@ module.exports = class fcoin extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_vol'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/flowbtc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/flowbtc.js index 12646489b..45d80935d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/flowbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/flowbtc.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -131,11 +132,11 @@ module.exports = class flowbtc extends Exchange { const currencyId = balance['name']; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['total'] = this.safeFloat (balance, 'hold'); + account['free'] = this.safeString (balance, 'balance'); + account['total'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -156,16 +157,16 @@ module.exports = class flowbtc extends Exchange { }; const ticker = await this.publicPostGetTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -175,8 +176,8 @@ module.exports = class flowbtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume24hr'), - 'quoteVolume': this.safeFloat (ticker, 'volume24hrProduct2'), + 'baseVolume': this.safeNumber (ticker, 'volume24hr'), + 'quoteVolume': this.safeNumber (ticker, 'volume24hrProduct2'), 'info': ticker, }; } @@ -185,14 +186,11 @@ module.exports = class flowbtc extends Exchange { const timestamp = this.safeTimestamp (trade, 'unixtime'); const side = (trade['incomingOrderSide'] === 0) ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'px'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'px'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'timestamp': timestamp, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/foxbit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/foxbit.js index 5830969a3..b1fb3032b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/foxbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/foxbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89,11 +90,11 @@ module.exports = class foxbit extends Exchange { // otherwise we will lose the info if the currency balance has been funded or traded or not if (currencyId in balances) { const account = this.account (); - let used = this.safeFloat (balances, currencyId + '_locked'); + let used = this.safeNumber (balances, currencyId + '_locked'); if (used !== undefined) { used *= 1e-8; } - let total = this.safeFloat (balances, currencyId); + let total = this.safeNumber (balances, currencyId); if (total !== undefined) { total *= 1e-8; } @@ -128,16 +129,16 @@ module.exports = class foxbit extends Exchange { const timestamp = this.milliseconds (); const lowercaseQuote = market['quote'].toLowerCase (); const quoteVolume = 'vol_' + lowercaseQuote; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -147,8 +148,8 @@ module.exports = class foxbit extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -161,14 +162,11 @@ module.exports = class foxbit extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ftx.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ftx.js index 18b572cc6..a0e42e8e4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ftx.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ftx.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending } = require ('./base/errors'); +const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending, ArgumentsRequired, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -243,6 +244,7 @@ module.exports = class ftx extends Exchange { 'An unexpected error occurred': ExchangeNotAvailable, // {"error":"An unexpected error occurred, please try again later (58BC21C795).","success":false} 'Please retry request': ExchangeNotAvailable, // {"error":"Please retry request","success":false} 'Please try again': ExchangeNotAvailable, // {"error":"Please try again","success":false} + 'Only have permissions for subaccount': PermissionDenied, // {"success":false,"error":"Only have permissions for subaccount *sub_name*"} }, }, 'precisionMode': TICK_SIZE, @@ -366,8 +368,8 @@ module.exports = class ftx extends Exchange { // check if a market is a spot or future market const symbol = (type === 'future') ? this.safeString (market, 'name') : (base + '/' + quote); const active = this.safeValue (market, 'enabled'); - const sizeIncrement = this.safeFloat (market, 'sizeIncrement'); - const priceIncrement = this.safeFloat (market, 'priceIncrement'); + const sizeIncrement = this.safeNumber (market, 'sizeIncrement'); + const priceIncrement = this.safeNumber (market, 'priceIncrement'); const precision = { 'amount': sizeIncrement, 'price': priceIncrement, @@ -445,28 +447,28 @@ module.exports = class ftx extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); const timestamp = this.safeTimestamp (ticker, 'time', this.milliseconds ()); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'change24h'), + 'percentage': this.safeNumber (ticker, 'change24h'), 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24h'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24h'), 'info': ticker, }; } @@ -506,14 +508,6 @@ module.exports = class ftx extends Exchange { return this.parseTicker (result, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetMarkets (params); @@ -592,11 +586,11 @@ module.exports = class ftx extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -717,6 +711,45 @@ module.exports = class ftx extends Exchange { // "type": "otc" // } // + // with -ve fee + // { + // "id": 1171258927, + // "fee": -0.0000713875, + // "side": "sell", + // "size": 1, + // "time": "2021-03-11T13:34:35.523627+00:00", + // "type": "order", + // "price": 14.2775, + // "future": null, + // "market": "SOL/USD", + // "feeRate": -0.000005, + // "orderId": 33182929044, + // "tradeId": 582936801, + // "liquidity": "maker", + // "feeCurrency": "USD", + // "baseCurrency": "SOL", + // "quoteCurrency": "USD" + // } + // + // // from OTC order + // { + // "id": 1172129651, + // "fee": 0, + // "side": "sell", + // "size": 1.47568846, + // "time": "2021-03-11T15:04:46.893383+00:00", + // "type": "otc", + // "price": 14.60932598, + // "future": null, + // "market": null, + // "feeRate": 0, + // "orderId": null, + // "tradeId": null, + // "liquidity": "taker", + // "feeCurrency": "USD", + // "baseCurrency": "BCHA", + // "quoteCurrency": "USD" + // } const id = this.safeString (trade, 'id'); const takerOrMaker = this.safeString (trade, 'liquidity'); const marketId = this.safeString (trade, 'market'); @@ -734,25 +767,24 @@ module.exports = class ftx extends Exchange { } } const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } const orderId = this.safeString (trade, 'orderId'); @@ -858,8 +890,8 @@ module.exports = class ftx extends Exchange { const result = this.safeValue (response, 'result', {}); return { 'info': response, - 'maker': this.safeFloat (result, 'makerFee'), - 'taker': this.safeFloat (result, 'takerFee'), + 'maker': this.safeNumber (result, 'makerFee'), + 'taker': this.safeNumber (result, 'takerFee'), }; } @@ -886,11 +918,11 @@ module.exports = class ftx extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'coin')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -1013,9 +1045,9 @@ module.exports = class ftx extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); let status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filledSize'); - let remaining = this.safeFloat (order, 'remainingSize'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filledSize'); + let remaining = this.safeNumber (order, 'remainingSize'); if ((remaining === 0.0) && (amount !== undefined) && (filled !== undefined)) { remaining = Math.max (amount - filled, 0); if (remaining > 0) { @@ -1039,15 +1071,15 @@ module.exports = class ftx extends Exchange { } const side = this.safeString (order, 'side'); const type = this.safeString (order, 'type'); - const average = this.safeFloat (order, 'avgFillPrice'); - const price = this.safeFloat2 (order, 'price', 'triggerPrice', average); + const average = this.safeNumber (order, 'avgFillPrice'); + const price = this.safeNumber2 (order, 'price', 'triggerPrice', average); let cost = undefined; if (filled !== undefined && price !== undefined) { cost = filled * price; } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'triggeredAt')); const clientOrderId = this.safeString (order, 'clientId'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -1093,22 +1125,28 @@ module.exports = class ftx extends Exchange { request['clientId'] = clientOrderId; params = this.omit (params, [ 'clientId', 'clientOrderId' ]); } - let priceToPrecision = undefined; - if (price !== undefined) { - priceToPrecision = parseFloat (this.priceToPrecision (symbol, price)); - } - let method = 'privatePostConditionalOrders'; + let method = undefined; if (type === 'limit') { method = 'privatePostOrders'; - request['price'] = priceToPrecision; + request['price'] = parseFloat (this.priceToPrecision (symbol, price)); } else if (type === 'market') { method = 'privatePostOrders'; request['price'] = null; } else if ((type === 'stop') || (type === 'takeProfit')) { - request['triggerPrice'] = priceToPrecision; - // request['orderPrice'] = number; // optional, order type is limit if this is specified, otherwise market + method = 'privatePostConditionalOrders'; + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerPrice'); + if (stopPrice === undefined) { + throw new ArgumentsRequired (this.id + ' createOrder () requires a stopPrice parameter or a triggerPrice parameter for ' + type + ' orders'); + } else { + params = this.omit (params, [ 'stopPrice', 'triggerPrice' ]); + request['triggerPrice'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + } + if (price !== undefined) { + request['orderPrice'] = parseFloat (this.priceToPrecision (symbol, price)); // optional, order type is limit if this is specified, otherwise market + } } else if (type === 'trailingStop') { - request['trailValue'] = priceToPrecision; // negative for "sell", positive for "buy" + method = 'privatePostConditionalOrders'; + request['trailValue'] = parseFloat (this.priceToPrecision (symbol, price)); // negative for "sell", positive for "buy" } else { throw new InvalidOrder (this.id + ' createOrder () does not support order type ' + type + ', only limit, market, stop, trailingStop, or takeProfit orders are supported'); } @@ -1174,9 +1212,9 @@ module.exports = class ftx extends Exchange { const request = {}; let method = undefined; const clientOrderId = this.safeString2 (params, 'client_order_id', 'clientOrderId'); - const triggerPrice = this.safeFloat (params, 'triggerPrice'); - const orderPrice = this.safeFloat (params, 'orderPrice'); - const trailValue = this.safeFloat (params, 'trailValue'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); + const orderPrice = this.safeNumber (params, 'orderPrice'); + const trailValue = this.safeNumber (params, 'trailValue'); params = this.omit (params, [ 'client_order_id', 'clientOrderId', 'triggerPrice', 'orderPrice', 'trailValue' ]); const triggerPriceIsDefined = (triggerPrice !== undefined); const orderPriceIsDefined = (orderPrice !== undefined); @@ -1539,7 +1577,7 @@ module.exports = class ftx extends Exchange { return this.parseTransaction (result, currency); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetAccount (params); // @@ -1672,7 +1710,7 @@ module.exports = class ftx extends Exchange { // const code = this.safeCurrencyCode (this.safeString (transaction, 'coin')); const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'size'); + const amount = this.safeNumber (transaction, 'size'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const txid = this.safeString (transaction, 'txid'); @@ -1689,7 +1727,7 @@ module.exports = class ftx extends Exchange { address = notes.slice (12); } } - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gateio.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gateio.js index f0835c774..eac7234c9 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gateio.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gateio.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, ArgumentsRequired, InvalidAddress, OrderNotFound, NotSupported, DDoSProtection, InsufficientFunds, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,9 +165,12 @@ module.exports = class gateio extends Exchange { }, }, 'commonCurrencies': { + '88MPH': 'MPH', + 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', + 'MPH': 'Morpher', // conflict with 88MPH 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', }, @@ -213,9 +217,9 @@ module.exports = class gateio extends Exchange { const currency = coin[id]; const code = this.safeCurrencyCode (id); const delisted = this.safeValue (currency, 'delisted', 0); - const withdrawDisabled = this.safeValue (currency, 'withdraw_disabled', 0); - const depositDisabled = this.safeValue (currency, 'deposit_disabled', 0); - const tradeDisabled = this.safeValue (currency, 'trade_disabled', 0); + const withdrawDisabled = this.safeInteger2 (currency, 'withdraw_disabled', 0); + const depositDisabled = this.safeInteger2 (currency, 'deposit_disabled', 0); + const tradeDisabled = this.safeInteger2 (currency, 'trade_disabled', 0); const listed = (delisted === 0); const withdrawEnabled = (withdrawDisabled === 0); const depositEnabled = (depositDisabled === 0); @@ -304,7 +308,7 @@ module.exports = class gateio extends Exchange { 'price': this.safeInteger (details, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (details, 'min_amount'), + 'min': this.safeNumber (details, 'min_amount'), 'max': undefined, }; const priceLimits = { @@ -312,7 +316,7 @@ module.exports = class gateio extends Exchange { 'max': undefined, }; const defaultCost = amountLimits['min'] * priceLimits['min']; - const minCost = this.safeFloat (this.options['limits']['cost']['min'], quote, defaultCost); + const minCost = this.safeNumber (this.options['limits']['cost']['min'], quote, defaultCost); const costLimits = { 'min': minCost, 'max': undefined, @@ -322,10 +326,10 @@ module.exports = class gateio extends Exchange { 'price': priceLimits, 'cost': costLimits, }; - const disabled = this.safeValue (details, 'trade_disabled'); + const disabled = this.safeInteger (details, 'trade_disabled'); const active = !disabled; const uppercaseId = id.toUpperCase (); - const fee = this.safeFloat (details, 'fee'); + const fee = this.safeNumber (details, 'fee'); result.push ({ 'id': id, 'uppercaseId': uppercaseId, @@ -359,11 +363,11 @@ module.exports = class gateio extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (available, currencyId); - account['used'] = this.safeFloat (locked, currencyId); + account['free'] = this.safeString (available, currencyId); + account['used'] = this.safeString (locked, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -379,11 +383,11 @@ module.exports = class gateio extends Exchange { // they return [ Timestamp, Volume, Close, High, Low, Open ] return [ this.safeInteger (ohlcv, 0), // t - this.safeFloat (ohlcv, 5), // o - this.safeFloat (ohlcv, 3), // h - this.safeFloat (ohlcv, 4), // l - this.safeFloat (ohlcv, 2), // c - this.safeFloat (ohlcv, 1), // v + this.safeNumber (ohlcv, 5), // o + this.safeNumber (ohlcv, 3), // h + this.safeNumber (ohlcv, 4), // l + this.safeNumber (ohlcv, 2), // c + this.safeNumber (ohlcv, 1), // v ]; } @@ -395,11 +399,11 @@ module.exports = class gateio extends Exchange { 'group_sec': this.timeframes[timeframe], }; // max limit = 1001 - if (limit !== undefined) { - const periodDurationInSeconds = this.parseTimeframe (timeframe); - const hours = parseInt ((periodDurationInSeconds * limit) / 3600); - request['range_hour'] = Math.max (0, hours - 1); - } + // if (limit !== undefined) { + // const periodDurationInSeconds = this.parseTimeframe (timeframe); + // const hours = parseInt ((periodDurationInSeconds * limit) / 3600); + // request['range_hour'] = Math.max (1, hours - 1); + // } const response = await this.publicGetCandlestick2Id (this.extend (request, params)); // // { @@ -423,8 +427,8 @@ module.exports = class gateio extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'percentChange'); let open = undefined; let change = undefined; let average = undefined; @@ -434,17 +438,17 @@ module.exports = class gateio extends Exchange { change = last - open; average = this.sum (last, open) / 2; } - open = this.safeFloat (ticker, 'open', open); - change = this.safeFloat (ticker, 'change', change); + open = this.safeNumber (ticker, 'open', open); + change = this.safeNumber (ticker, 'change', change); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high24hr', 'high'), - 'low': this.safeFloat2 (ticker, 'low24hr', 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber2 (ticker, 'high24hr', 'high'), + 'low': this.safeNumber2 (ticker, 'low24hr', 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -454,8 +458,8 @@ module.exports = class gateio extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), // gateio has them reversed - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), // gateio has them reversed + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -501,27 +505,24 @@ module.exports = class gateio extends Exchange { const id = this.safeString2 (trade, 'tradeID', 'id'); // take either of orderid or orderId const orderId = this.safeString2 (trade, 'orderid', 'orderNumber'); - const price = this.safeFloat2 (trade, 'rate', 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString2 (trade, 'rate', 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'role'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } let fee = undefined; let feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee_coin')); - let feeCost = this.safeFloat (trade, 'point_fee'); + let feeCost = this.safeNumber (trade, 'point_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'gt_fee'); + feeCost = this.safeNumber (trade, 'gt_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'fee'); + feeCost = this.safeNumber (trade, 'fee'); } else { feeCurrency = this.safeCurrencyCode ('GT'); } @@ -665,23 +666,20 @@ module.exports = class gateio extends Exchange { } else if (side === '2') { side = 'buy'; } - const price = this.safeFloat2 (order, 'initialRate', 'rate'); - const average = this.safeFloat (order, 'filledRate'); - const amount = this.safeFloat2 (order, 'initialAmount', 'amount'); - const filled = this.safeFloat (order, 'filledAmount'); + const price = this.safeNumber2 (order, 'initialRate', 'rate'); + const average = this.safeNumber (order, 'filledRate'); + const amount = this.safeNumber2 (order, 'initialAmount', 'amount'); + const filled = this.safeNumber (order, 'filledAmount'); // In the order status response, this field has a different name. - let remaining = this.safeFloat2 (order, 'leftAmount', 'left'); - if (remaining === undefined) { - remaining = amount - filled; - } - const feeCost = this.safeFloat (order, 'feeValue'); + const remaining = this.safeNumber2 (order, 'leftAmount', 'left'); + const feeCost = this.safeNumber (order, 'feeValue'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (order, 'feePercentage'); + let feeRate = this.safeNumber (order, 'feePercentage'); if (feeRate !== undefined) { feeRate = feeRate / 100; } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -707,7 +705,7 @@ module.exports = class gateio extends Exchange { 'rate': feeRate, }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -898,7 +896,7 @@ module.exports = class gateio extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'txid'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); if (address === 'false') { address = undefined; @@ -906,7 +904,7 @@ module.exports = class gateio extends Exchange { const timestamp = this.safeTimestamp (transaction, 'timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.parseTransactionType (id[0]); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gemini.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gemini.js index 6f28ef220..36892fa47 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gemini.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gemini.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidOrder, InvalidNonce, InsufficientFunds, AuthenticationError, PermissionDenied, NotSupported, OnMaintenance, RateLimitExceeded, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -221,16 +222,16 @@ module.exports = class gemini extends Exchange { // const base = this.safeCurrencyCode (baseId); const minAmountString = cells[1].replace ('', ''); const minAmountParts = minAmountString.split (' '); - const minAmount = this.safeFloat (minAmountParts, 0); + const minAmount = this.safeNumber (minAmountParts, 0); const amountPrecisionString = cells[2].replace ('', ''); const amountPrecisionParts = amountPrecisionString.split (' '); - const amountPrecision = this.safeFloat (amountPrecisionParts, 0); + const amountPrecision = this.safeNumber (amountPrecisionParts, 0); const idLength = marketId.length - 0; const quoteId = marketId.slice (idLength - 3, idLength); const quote = this.safeCurrencyCode (quoteId); const pricePrecisionString = cells[3].replace ('', ''); const pricePrecisionParts = pricePrecisionString.split (' '); - const pricePrecision = this.safeFloat (pricePrecisionParts, 0); + const pricePrecision = this.safeNumber (pricePrecisionParts, 0); const baseId = marketId.replace (quoteId, ''); const base = this.safeCurrencyCode (baseId); const symbol = base + '/' + quote; @@ -458,11 +459,11 @@ module.exports = class gemini extends Exchange { base = market['base']; quote = market['quote']; } - const price = this.safeFloat (ticker, 'price'); - const last = this.safeFloat2 (ticker, 'last', 'close', price); - let percentage = this.safeFloat (ticker, 'percentChange24h'); + const price = this.safeNumber (ticker, 'price'); + const last = this.safeNumber2 (ticker, 'last', 'close', price); + let percentage = this.safeNumber (ticker, 'percentChange24h'); let change = undefined; - let open = this.safeFloat (ticker, 'open'); + let open = this.safeNumber (ticker, 'open'); let average = undefined; if (last !== undefined) { if (open !== undefined) { @@ -479,18 +480,18 @@ module.exports = class gemini extends Exchange { average = this.sum (last, open) / 2; } } - const baseVolume = this.safeFloat (volume, baseId); - const quoteVolume = this.safeFloat (volume, quoteId); + const baseVolume = this.safeNumber (volume, baseId); + const quoteVolume = this.safeNumber (volume, quoteId); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -506,14 +507,6 @@ module.exports = class gemini extends Exchange { }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetV1Pricefeed (params); @@ -554,17 +547,14 @@ module.exports = class gemini extends Exchange { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); const fee = { - 'cost': this.safeFloat (trade, 'fee_amount'), + 'cost': this.safeNumber (trade, 'fee_amount'), 'currency': feeCurrencyCode, }; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeStringLower (trade, 'type'); const symbol = this.safeSymbol (undefined, market); @@ -617,18 +607,18 @@ module.exports = class gemini extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'timestampms'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const filled = this.safeFloat (order, 'executed_amount'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const filled = this.safeNumber (order, 'executed_amount'); let status = 'closed'; if (order['is_live']) { status = 'open'; @@ -636,14 +626,8 @@ module.exports = class gemini extends Exchange { if (order['is_cancelled']) { status = 'canceled'; } - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_execution_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_execution_price'); let type = this.safeString (order, 'type'); if (type === 'exchange limit') { type = 'limit'; @@ -658,7 +642,7 @@ module.exports = class gemini extends Exchange { const id = this.safeString (order, 'order_id'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'client_order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -674,13 +658,13 @@ module.exports = class gemini extends Exchange { 'price': price, 'stopPrice': undefined, 'average': average, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -795,7 +779,7 @@ module.exports = class gemini extends Exchange { status = 'ok'; } let fee = undefined; - const feeAmount = this.safeFloat (transaction, 'feeAmount'); + const feeAmount = this.safeNumber (transaction, 'feeAmount'); if (feeAmount !== undefined) { fee = { 'cost': feeAmount, @@ -811,7 +795,7 @@ module.exports = class gemini extends Exchange { 'address': address, 'tag': undefined, // or is it defined? 'type': type, // direction of the transaction, ('deposit' | 'withdraw') - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gopax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gopax.js index e3150163a..b27308f19 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gopax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/gopax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors'); const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -218,8 +219,8 @@ module.exports = class gopax extends Exchange { const minimums = this.safeValue (market, 'restApiOrderAmountMin', {}); const marketAsk = this.safeValue (minimums, 'marketAsk', {}); const marketBid = this.safeValue (minimums, 'marketBid', {}); - const takerFeePercent = this.safeFloat (market, 'takerFeePercent'); - const makerFeePercent = this.safeFloat (market, 'makerFeePercent'); + const takerFeePercent = this.safeNumber (market, 'takerFeePercent'); + const makerFeePercent = this.safeNumber (market, 'makerFeePercent'); const taker = parseFloat (this.decimalToPrecision (takerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); const maker = parseFloat (this.decimalToPrecision (makerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); result.push ({ @@ -237,15 +238,15 @@ module.exports = class gopax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (marketAsk, 'amount'), + 'min': this.safeNumber (marketAsk, 'amount'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'priceMin'), + 'min': this.safeNumber (market, 'priceMin'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (marketBid, 'amount'), + 'min': this.safeNumber (marketBid, 'amount'), 'max': undefined, }, }, @@ -280,8 +281,8 @@ module.exports = class gopax extends Exchange { const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'name'); - const fee = this.safeFloat (currency, 'withdrawalFee'); - const precision = this.safeFloat (currency, 'scale'); + const fee = this.safeNumber (currency, 'withdrawalFee'); + const precision = this.safeNumber (currency, 'scale'); result[code] = { 'id': id, 'info': currency, @@ -304,7 +305,7 @@ module.exports = class gopax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalAmountMin'), + 'min': this.safeNumber (currency, 'withdrawalAmountMin'), 'max': undefined, }, }, @@ -372,8 +373,8 @@ module.exports = class gopax extends Exchange { const marketId = this.safeString (ticker, 'name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (ticker, 'time')); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat2 (ticker, 'price', 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'price', 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -384,20 +385,20 @@ module.exports = class gopax extends Exchange { percentage = change / open * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidVolume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askVolume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidVolume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askVolume'), 'vwap': vwap, 'open': open, 'close': last, @@ -433,14 +434,6 @@ module.exports = class gopax extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTradingPairsStats (params); @@ -462,8 +455,8 @@ module.exports = class gopax extends Exchange { parsePublicTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let symbol = undefined; if ('symbol' in market) { symbol = this.safeString (market, 'symbol'); @@ -489,14 +482,14 @@ module.exports = class gopax extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const symbol = this.safeString (trade, 'tradingPairName').replace ('-', '/'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'baseAmount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'baseAmount'); let feeCurrency = symbol.slice (0, 3); if (side === 'sell') { feeCurrency = symbol.slice (4); } const fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': feeCurrency, 'rate': undefined, }; @@ -578,15 +571,15 @@ module.exports = class gopax extends Exchange { } else if (type === '2') { type = 'market'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'baseAmount'); - let cost = this.safeFloat (trade, 'quoteAmount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'baseAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteAmount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -653,11 +646,11 @@ module.exports = class gopax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -697,14 +690,14 @@ module.exports = class gopax extends Exchange { const balance = response[i]; const currencyId = this.safeString2 (balance, 'asset', 'isoAlpha3'); const code = this.safeCurrencyCode (currencyId); - const hold = this.safeFloat (balance, 'hold'); - const pendingWithdrawal = this.safeFloat (balance, 'pendingWithdrawal'); + const hold = this.safeString (balance, 'hold'); + const pendingWithdrawal = this.safeString (balance, 'pendingWithdrawal'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.sum (hold, pendingWithdrawal); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = Precise.stringAdd (hold, pendingWithdrawal); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -781,42 +774,36 @@ module.exports = class gopax extends Exchange { const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); const timeInForce = this.safeStringUpper (order, 'timeInForce'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - const remaining = this.safeFloat (order, 'remaining'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const stopPrice = this.safeNumber (order, 'stopPrice'); + const remaining = this.safeNumber (order, 'remaining'); const marketId = this.safeString (order, 'tradingPairName'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const balanceChange = this.safeValue (order, 'balanceChange', {}); - let filled = this.safeFloat (balanceChange, 'baseNet'); - let cost = this.safeFloat (balanceChange, 'quoteNet'); + const filled = this.safeNumber (balanceChange, 'baseNet'); + let cost = this.safeNumber (balanceChange, 'quoteNet'); if (cost !== undefined) { cost = Math.abs (cost); } let updated = undefined; - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } if ((filled !== undefined) && (filled > 0)) { updated = this.parse8601 (this.safeString (order, 'updatedAt')); } - if ((cost === undefined) && (price !== undefined) && (filled !== undefined)) { - cost = filled * price; - } let fee = undefined; if (side === 'buy') { const baseFee = this.safeValue (balanceChange, 'baseFee', {}); - const taking = this.safeFloat (baseFee, 'taking'); - const making = this.safeFloat (baseFee, 'making'); + const taking = this.safeNumber (baseFee, 'taking'); + const making = this.safeNumber (baseFee, 'making'); fee = { 'currency': market['base'], 'cost': this.sum (taking, making), }; } else { const quoteFee = this.safeValue (balanceChange, 'quoteFee', {}); - const taking = this.safeFloat (quoteFee, 'taking'); - const making = this.safeFloat (quoteFee, 'making'); + const taking = this.safeNumber (quoteFee, 'taking'); + const making = this.safeNumber (quoteFee, 'making'); fee = { 'currency': market['quote'], 'cost': this.sum (taking, making), @@ -826,7 +813,7 @@ module.exports = class gopax extends Exchange { if (timeInForce !== undefined) { postOnly = (timeInForce === 'PO'); } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'datetime': this.iso8601 (timestamp), @@ -848,7 +835,7 @@ module.exports = class gopax extends Exchange { 'trades': undefined, 'fee': fee, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -996,7 +983,7 @@ module.exports = class gopax extends Exchange { request['clientOrderId'] = clientOrderId; params = this.omit (params, 'clientOrderId'); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1125,18 +1112,6 @@ module.exports = class gopax extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetCryptoDepositAddresses (params); @@ -1201,8 +1176,8 @@ module.exports = class gopax extends Exchange { } else if ((type === 'crypto_deposit' || type === 'fiat_deposit')) { type = 'deposit'; } - const amount = this.safeFloat (transaction, 'netAmount'); - const feeCost = this.safeFloat (transaction, 'feeAmount'); + const amount = this.safeNumber (transaction, 'netAmount'); + const feeCost = this.safeNumber (transaction, 'feeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hbtc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hbtc.js index d819c3d77..5dfd98ec5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hbtc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -304,23 +305,23 @@ module.exports = class hbtc extends Exchange { const filter = filters[j]; const filterType = this.safeString (filter, 'filterType'); if (filterType === 'LOT_SIZE') { - amountMin = this.safeFloat (filter, 'minQty'); - amountMax = this.safeFloat (filter, 'maxQty'); + amountMin = this.safeNumber (filter, 'minQty'); + amountMax = this.safeNumber (filter, 'maxQty'); } if (filterType === 'PRICE_FILTER') { - priceMin = this.safeFloat (filter, 'minPrice'); - priceMax = this.safeFloat (filter, 'maxPrice'); + priceMin = this.safeNumber (filter, 'minPrice'); + priceMax = this.safeNumber (filter, 'maxPrice'); } if (filterType === 'MIN_NOTIONAL') { - costMin = this.safeFloat (filter, 'minNotional'); + costMin = this.safeNumber (filter, 'minNotional'); } } if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) { costMin = amountMin * priceMin; } const precision = { - 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'), - 'amount': this.safeFloat (market, 'baseAssetPrecision'), + 'price': this.safeNumber2 (market, 'quotePrecision', 'quoteAssetPrecision'), + 'amount': this.safeNumber (market, 'baseAssetPrecision'), }; const limits = { 'amount': { @@ -558,14 +559,6 @@ module.exports = class hbtc extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidAsk (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -717,8 +710,8 @@ module.exports = class hbtc extends Exchange { const currencyId = this.safeString2 (balance, 'asset', 'tokenName'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -728,12 +721,12 @@ module.exports = class hbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = response[currencyId]; const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableMargin'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'availableMargin'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTrades (symbol, since = undefined, limit = 50, params = {}) { @@ -774,11 +767,11 @@ module.exports = class hbtc extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -1464,8 +1457,8 @@ module.exports = class hbtc extends Exchange { // const currencyId = this.safeString (item, 'tokenId'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'change'); - const after = this.safeFloat (item, 'total'); + const amount = this.safeNumber (item, 'change'); + const after = this.safeNumber (item, 'total'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -1605,8 +1598,8 @@ module.exports = class hbtc extends Exchange { } else { type = 'withdrawal'; } - const amount = this.safeFloat (transaction, 'quantity'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'quantity'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'feeTokenId'); @@ -1667,8 +1660,8 @@ module.exports = class hbtc extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'openPrice'); - const close = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; let average = undefined; @@ -1679,19 +1672,19 @@ module.exports = class hbtc extends Exchange { percentage = (change / open) * 100; } } - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber2 (ticker, 'bestBidPrice', 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber2 (ticker, 'bestAskPrice', 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': vwap, 'open': open, 'close': close, @@ -1741,17 +1734,14 @@ module.exports = class hbtc extends Exchange { // } // const id = this.safeString (trade, 'id'); - const timestamp = this.safeFloat (trade, 'time'); + const timestamp = this.safeNumber (trade, 'time'); const type = undefined; const orderId = this.safeString (trade, 'orderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let side = undefined; let takerOrMaker = undefined; if ('isBuyerMaker' in trade) { @@ -1765,7 +1755,7 @@ module.exports = class hbtc extends Exchange { side = isBuyer ? 'buy' : 'sell'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1871,30 +1861,30 @@ module.exports = class hbtc extends Exchange { const symbol = this.safeSymbol (marketId, market); let type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'avgPrice'); + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'avgPrice'); let amount = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); + let cost = this.safeNumber (order, 'cummulativeQuoteQty'); let filled = undefined; let remaining = undefined; if (type === undefined) { type = this.safeStringLower (order, 'orderType'); if ((market !== undefined) && market['inverse']) { - cost = this.safeFloat (order, 'executedQty'); + cost = this.safeNumber (order, 'executedQty'); amount = undefined; } if (cost === 0.0) { filled = 0; } } else { - amount = this.safeFloat (order, 'origQty'); + amount = this.safeNumber (order, 'origQty'); if (type === 'market') { price = undefined; if (side === 'buy') { amount = undefined; } } - filled = this.safeFloat (order, 'executedQty'); + filled = this.safeNumber (order, 'executedQty'); if (filled !== undefined) { if (amount !== undefined) { remaining = amount - filled; @@ -1906,7 +1896,7 @@ module.exports = class hbtc extends Exchange { } const status = this.parseOrderStatus (this.safeString (order, 'status')); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const result = { 'info': order, 'id': id, @@ -1935,7 +1925,7 @@ module.exports = class hbtc extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'fee'); + const feeCost = this.safeNumber (fees[i], 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'feeToken'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hitbtc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hitbtc.js index b66392816..b7fd38b04 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hitbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hitbtc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, PermissionDenied, ExchangeError, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, RequestTimeout, AuthenticationError } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -44,6 +45,7 @@ module.exports = class hitbtc extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': 'M1', @@ -81,10 +83,10 @@ module.exports = class hitbtc extends Exchange { 'api': { 'public': { 'get': [ - 'symbol', // Available Currency Symbols - 'symbol/{symbol}', // Get symbol info 'currency', // Available Currencies 'currency/{currency}', // Get currency info + 'symbol', // Available Currency Symbols + 'symbol/{symbol}', // Get symbol info 'ticker', // Ticker list for all symbols 'ticker/{symbol}', // Ticker for symbol 'trades', @@ -102,11 +104,20 @@ module.exports = class hitbtc extends Exchange { 'order/{clientOrderId}', // Get a single order by clientOrderId 'trading/fee/all', // Get trading fee rate 'trading/fee/{symbol}', // Get trading fee rate + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', 'history/order', // Get historical orders 'history/trades', // Get historical trades 'history/order/{orderId}/trades', // Get historical trades by specified order 'account/balance', // Get main acccount balance - 'account/crypto/address/{currency}', // Get deposit crypro address + 'account/crypto/address/{currency}', // Get current address + 'account/crypto/addresses/{currency}', // Get last 10 deposit addresses for currency + 'account/crypto/used-addresses/{currency}', // Get last 10 unique addresses used for withdraw by currency + 'account/crypto/estimate-withdraw', 'account/crypto/is-mine/{address}', 'account/transactions', // Get account transactions 'account/transactions/{id}', // Get account transaction by id @@ -117,23 +128,33 @@ module.exports = class hitbtc extends Exchange { ], 'post': [ 'order', // Create new order - 'account/crypto/address/{currency}', // Create new deposit crypro address - 'account/crypto/withdraw', // Withdraw crypro + 'margin/order', + 'account/crypto/address/{currency}', // Create new crypto deposit address + 'account/crypto/withdraw', // Withdraw crypto 'account/crypto/transfer-convert', - 'account/transfer', // Transfer amount to trading + 'account/transfer', // Transfer amount to trading account or to main account + 'account/transfer/internal', 'sub-acc/freeze', 'sub-acc/activate', 'sub-acc/transfer', ], 'put': [ 'order/{clientOrderId}', // Create new order - 'account/crypto/withdraw/{id}', // Commit withdraw crypro + 'margin/account/{symbol}', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Commit crypto withdrawal 'sub-acc/acl/{subAccountUserId}', ], 'delete': [ 'order', // Cancel all open orders 'order/{clientOrderId}', // Cancel order - 'account/crypto/withdraw/{id}', // Rollback withdraw crypro + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Rollback crypto withdrawal ], // outdated? 'patch': [ @@ -152,8 +173,20 @@ module.exports = class hitbtc extends Exchange { }, 'options': { 'defaultTimeInForce': 'FOK', + 'accountsByType': { + 'bank': 'bank', + 'exchange': 'exchange', + 'main': 'bank', // alias of the above + 'trading': 'exchange', + }, + 'fetchBalanceMethod': { + 'account': 'account', + 'main': 'account', + 'trading': 'trading', + }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive 'BET': 'DAO.Casino', 'BOX': 'BOX Token', @@ -180,7 +213,6 @@ module.exports = class hitbtc extends Exchange { '20002': OrderNotFound, // canceling non-existent order '20001': InsufficientFunds, // {"error":{"code":20001,"message":"Insufficient funds","description":"Check that the funds are sufficient, given commissions"}} }, - 'orders': {}, // orders cache / emulation }); } @@ -217,14 +249,14 @@ module.exports = class hitbtc extends Exchange { if (id.indexOf ('_') >= 0) { symbol = id; } - const lot = this.safeFloat (market, 'quantityIncrement'); - const step = this.safeFloat (market, 'tickSize'); + const lot = this.safeNumber (market, 'quantityIncrement'); + const step = this.safeNumber (market, 'tickSize'); const precision = { 'price': step, 'amount': lot, }; - const taker = this.safeFloat (market, 'takeLiquidityRate'); - const maker = this.safeFloat (market, 'provideLiquidityRate'); + const taker = this.safeNumber (market, 'takeLiquidityRate'); + const maker = this.safeNumber (market, 'provideLiquidityRate'); const feeCurrencyId = this.safeString (market, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); result.push (this.extend (this.fees['trading'], { @@ -259,6 +291,49 @@ module.exports = class hitbtc extends Exchange { return result; } + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // account can be "exchange" or "bank", with aliases "main" or "trading" respectively + await this.loadMarkets (); + const currency = this.currency (code); + const requestAmount = this.currencyToPrecision (code, amount); + const request = { + 'currency': currency['id'], + 'amount': requestAmount, + }; + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + const keys = Object.keys (accountsByType); + if (fromId === undefined) { + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ') + ' instead of ' + fromId); + } + if (toId === undefined) { + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ') + ' instead of ' + toId); + } + if (fromId === toId) { + throw new ExchangeError (this.id + ' from and to cannot be the same account'); + } + type = fromId + 'To' + this.capitalize (toId); + } + request['type'] = type; + const response = await this.privatePostAccountTransfer (this.extend (request, params)); + // { id: '2db6ebab-fb26-4537-9ef8-1a689472d236' } + const id = this.safeString (response, 'id'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'amount': requestAmount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': undefined, + }; + } + async fetchCurrencies (params = {}) { const response = await this.publicGetCurrency (params); // @@ -314,7 +389,7 @@ module.exports = class hitbtc extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'payoutFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'payoutFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -354,15 +429,20 @@ module.exports = class hitbtc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } async fetchBalance (params = {}) { await this.loadMarkets (); const type = this.safeString (params, 'type', 'trading'); - const method = 'privateGet' + this.capitalize (type) + 'Balance'; + const fetchBalanceAccounts = this.safeValue (this.options, 'fetchBalanceMethod', {}); + const typeId = this.safeString (fetchBalanceAccounts, type); + if (typeId === undefined) { + throw new ExchangeError (this.id + ' fetchBalance account type must be either main or trading'); + } + const method = 'privateGet' + this.capitalize (typeId) + 'Balance'; const query = this.omit (params, 'type'); const response = await this[method] (query); const result = { 'info': response }; @@ -371,11 +451,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -392,11 +472,11 @@ module.exports = class hitbtc extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'max'), - this.safeFloat (ohlcv, 'min'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'max'), + this.safeNumber (ohlcv, 'min'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -442,10 +522,10 @@ module.exports = class hitbtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); let change = undefined; let percentage = undefined; let average = undefined; @@ -461,11 +541,11 @@ module.exports = class hitbtc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -541,7 +621,7 @@ module.exports = class hitbtc extends Exchange { market = this.safeMarket (marketId, market); const symbol = market['symbol']; let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = market ? market['feeCurrency'] : undefined; fee = { @@ -553,9 +633,11 @@ module.exports = class hitbtc extends Exchange { // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const orderId = this.safeString (trade, 'clientOrderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); const id = this.safeString (trade, 'id'); return { @@ -654,11 +736,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'hash'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -846,66 +928,25 @@ module.exports = class hitbtc extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'cumQuantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'cumQuantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); // we use clientOrderId as the order id with this exchange intentionally // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const id = this.safeString (order, 'clientOrderId'); const clientOrderId = id; - let price = this.safeFloat (order, 'price'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - if (price !== undefined) { - cost = filled * price; - } - } - } + const price = this.safeNumber (order, 'price'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); let trades = this.safeValue (order, 'tradesReport'); - let fee = undefined; - let average = this.safeValue (order, 'avgPrice'); + const fee = undefined; + const average = this.safeNumber (order, 'avgPrice'); if (trades !== undefined) { trades = this.parseTrades (trades, market); - let feeCost = undefined; - const numTrades = trades.length; - let tradesCost = 0; - for (let i = 0; i < numTrades; i++) { - if (feeCost === undefined) { - feeCost = 0; - } - tradesCost = this.sum (tradesCost, trades[i]['cost']); - const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); - if (tradeFeeCost !== undefined) { - feeCost = this.sum (feeCost, tradeFeeCost); - } - } - cost = tradesCost; - if ((filled !== undefined) && (filled > 0)) { - if (average === undefined) { - average = cost / filled; - } - if (type === 'market') { - if (price === undefined) { - price = average; - } - } - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, // https://github.com/ccxt/ccxt/issues/5674 'timestamp': created, @@ -920,13 +961,13 @@ module.exports = class hitbtc extends Exchange { 'stopPrice': undefined, 'average': average, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hollaex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hollaex.js index 52e81fec3..bde50ed15 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hollaex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/hollaex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadRequest, AuthenticationError, NetworkError, ArgumentsRequired, OrderNotFound, InsufficientFunds } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -15,7 +16,7 @@ module.exports = class hollaex extends Exchange { 'name': 'HollaEx', 'countries': [ 'KR' ], 'rateLimit': 333, - 'version': 'v1', + 'version': 'v2', 'has': { 'CORS': false, 'fetchMarkets': true, @@ -35,13 +36,13 @@ module.exports = class hollaex extends Exchange { 'cancelOrder': true, 'cancelAllOrders': true, 'fetchOpenOrders': true, - 'fetchClosedOrders': false, + 'fetchClosedOrders': true, 'fetchOpenOrder': true, 'fetchOrder': false, 'fetchDeposits': true, 'fetchWithdrawals': true, 'fetchTransactions': false, - 'fetchOrders': false, + 'fetchOrders': true, 'fetchMyTrades': true, 'withdraw': true, 'fetchDepositAddress': true, @@ -66,13 +67,17 @@ module.exports = class hollaex extends Exchange { 'public': { 'get': [ 'health', - 'constant', + 'constants', + 'kit', + 'tiers', 'ticker', - 'ticker/all', + 'tickers', + 'orderbook', 'orderbooks', 'trades', 'chart', - // TradingView data + 'charts', + // TradingView 'udf/config', 'udf/history', 'udf/symbols', @@ -82,20 +87,20 @@ module.exports = class hollaex extends Exchange { 'get': [ 'user', 'user/balance', - 'user/trades', - 'user/orders', - 'user/orders/{order_id}', 'user/deposits', 'user/withdrawals', - 'user/withdraw/{currency}/fee', + 'user/withdrawal/fee', + 'user/trades', + 'orders', + 'orders/{order_id}', ], 'post': [ 'user/request-withdrawal', 'order', ], 'delete': [ - 'user/orders', - 'user/orders/{order_id}', + 'order/all', + 'order', ], }, }, @@ -130,7 +135,7 @@ module.exports = class hollaex extends Exchange { } async fetchMarkets (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); // // { // coins: { @@ -197,17 +202,17 @@ module.exports = class hollaex extends Exchange { 'quoteId': quoteId, 'active': active, 'precision': { - 'price': this.safeFloat (market, 'increment_price'), - 'amount': this.safeFloat (market, 'increment_size'), + 'price': this.safeNumber (market, 'increment_price'), + 'amount': this.safeNumber (market, 'increment_size'), }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, 'max': undefined }, }, @@ -218,7 +223,7 @@ module.exports = class hollaex extends Exchange { } async fetchCurrencies (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); const coins = this.safeValue (response, 'coins', {}); const keys = Object.keys (coins); const result = {}; @@ -230,8 +235,8 @@ module.exports = class hollaex extends Exchange { const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'fullname'); const active = this.safeValue (currency, 'active'); - const fee = this.safeFloat (currency, 'withdrawal_fee'); - const precision = this.safeFloat (currency, 'increment_unit'); + const fee = this.safeNumber (currency, 'withdrawal_fee'); + const precision = this.safeNumber (currency, 'increment_unit'); const withdrawalLimits = this.safeValue (currency, 'withdrawal_limits', []); result[code] = { 'id': id, @@ -244,8 +249,8 @@ module.exports = class hollaex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min'), - 'max': this.safeFloat (currency, 'max'), + 'min': this.safeNumber (currency, 'min'), + 'max': this.safeNumber (currency, 'max'), }, 'price': { 'min': undefined, @@ -334,7 +339,7 @@ module.exports = class hollaex extends Exchange { async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.publicGetTickerAll (this.extend (params)); + const response = await this.publicGetTickers (this.extend (params)); // // { // "bch-usdt": { @@ -397,27 +402,27 @@ module.exports = class hollaex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString2 (ticker, 'time', 'timestamp')); - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const result = { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, - 'last': this.safeFloat (ticker, 'last', close), + 'last': this.safeNumber (ticker, 'last', close), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, }; return result; @@ -475,15 +480,12 @@ module.exports = class hollaex extends Exchange { const datetime = this.safeString (trade, 'timestamp'); const timestamp = this.parse8601 (datetime); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const quote = market['quote']; @@ -568,11 +570,11 @@ module.exports = class hollaex extends Exchange { // return [ this.parse8601 (this.safeString (response, 'time')), - this.safeFloat (response, 'open'), - this.safeFloat (response, 'high'), - this.safeFloat (response, 'low'), - this.safeFloat (response, 'close'), - this.safeFloat (response, 'volume'), + this.safeNumber (response, 'open'), + this.safeNumber (response, 'high'), + this.safeNumber (response, 'low'), + this.safeNumber (response, 'close'), + this.safeNumber (response, 'volume'), ]; } @@ -597,11 +599,11 @@ module.exports = class hollaex extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (response, currencyId + '_available'); - account['total'] = this.safeFloat (response, currencyId + '_balance'); + account['free'] = this.safeString (response, currencyId + '_available'); + account['total'] = this.safeString (response, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrder (id, symbol = undefined, params = {}) { @@ -609,67 +611,146 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateGetUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateGetOrdersOrderId (this.extend (request, params)); // // { - // "created_at": "2018-03-23T04:14:08.663Z", - // "title": "string", - // "side": "sell", - // "type": "limit", - // "price": 0, - // "size": 0, - // "symbol": "xht-usdt", // "id": "string", - // "created_by": 1, - // "filled": 0 + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } // } // return this.parseOrder (response); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'open': true, + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'status': 'filled', + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = undefined; - const request = {}; + const request = { + // 'symbol': market['id'], + // 'side': 'buy', // 'sell' + // 'status': 'new', // 'filled', 'pfilled', 'canceled' + // 'open': true, + // 'limit': limit, // default 50, max 100 + // 'page': 1, + // 'order_by': 'created_at', // id, ... + // 'order': 'asc', // 'desc' + // 'start_date': this.iso8601 (since), + // 'end_date': this.iso8601 (this.milliseconds ()), + }; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } - const response = await this.privateGetUserOrders (this.extend (request, params)); + if (since !== undefined) { + request['start_date'] = this.iso8601 (since); + } + if (limit !== undefined) { + request['limit'] = limit; // default 50, max 100 + } + const response = await this.privateGetOrders (this.extend (request, params)); // - // [ - // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 - // } - // ] + // { + // "count": 1, + // "data": [ + // { + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } + // } + // ] + // } // - return this.parseOrders (response, market); + const data = this.safeValue (response, 'data', []); + return this.parseOrders (data, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'new': 'open', + 'pfilled': 'open', + 'filled': 'closed', + 'canceled': 'canceled', + }; + return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // - // fetchOpenOrder, fetchOpenOrders + // createOrder, fetchOpenOrder, fetchOpenOrders // // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // }, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, // } // const marketId = this.safeString (order, 'symbol'); @@ -678,21 +759,11 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filled'); - let cost = undefined; - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = filled * price; - } - } - const status = (type === 'market') ? 'closed' : 'open'; - const result = { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filled'); + const status = this.parseOrderStatus (this.safeString (order, 'status')); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -708,40 +779,56 @@ module.exports = class hollaex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; - return result; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); - const order = { + const request = { 'symbol': market['id'], 'side': side, 'size': amount, 'type': type, + // 'stop': parseFloat (this.priceToPrecision (symbol, stopPrice)), + // 'meta': {}, // other options such as post_only }; if (type !== 'market') { - order['price'] = price; + request['price'] = price; } - const response = await this.privatePostOrder (this.extend (order, params)); + const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop'); + if (stopPrice !== undefined) { + request['stop'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + params = this.omit (params, [ 'stopPrice', 'stop' ]); + } + const response = await this.privatePostOrder (this.extend (request, params)); // // { + // "fee": 0, + // "meta": {}, // "symbol": "xht-usdt", // "side": "sell", - // "size": 1, + // "size": 0.1, // "type": "limit", - // "price": 0.1, + // "price": 1, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, + // "fee_coin": "usdt", // "id": "string", - // "created_by": 34, + // "created_by": 116, // "filled": 0, - // "status": "pending" + // "status": "new", + // "updated_at": "2021-02-17T03:03:19.231Z", + // "created_at": "2021-02-17T03:03:19.231Z", + // "stop": null // } // return this.parseOrder (response, market); @@ -752,7 +839,7 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateDeleteUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateDeleteOrder (this.extend (request, params)); // // { // "title": "string", @@ -777,7 +864,7 @@ module.exports = class hollaex extends Exchange { market = this.markets (symbol); request['symbol'] = market['id']; } - const response = await this.privateDeleteUserOrders (this.extend (request, params)); + const response = await this.privateDeleteOrderAll (this.extend (request, params)); // // [ // { @@ -1043,7 +1130,7 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_at')); const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const type = this.safeString (transaction, 'type'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); let addressTo = undefined; const addressFrom = undefined; @@ -1073,7 +1160,7 @@ module.exports = class hollaex extends Exchange { } const fee = { 'currency': code, - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), }; return { 'info': transaction, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/huobipro.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/huobipro.js index 52dc315e8..22c1d91d5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/huobipro.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/huobipro.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, ExchangeNotAvailable, OnMaintenance, InvalidOrder, OrderNotFound, InsufficientFunds, ArgumentsRequired, BadSymbol, BadRequest, RequestTimeout, NetworkError } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -22,7 +23,9 @@ module.exports = class huobipro extends Exchange { 'hostname': 'api.huobi.pro', // api.testnet.huobi.pro 'pro': true, 'has': { + 'cancelAllOrders': true, 'cancelOrder': true, + 'cancelOrders': true, 'CORS': false, 'createOrder': true, 'fetchBalance': true, @@ -189,6 +192,7 @@ module.exports = class huobipro extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.002, @@ -252,6 +256,7 @@ module.exports = class huobipro extends Exchange { // https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/ 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', + 'BIFI': 'Bitcoin File', // conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706 }, }); } @@ -316,8 +321,8 @@ module.exports = class huobipro extends Exchange { 'info': limits, 'limits': { 'amount': { - 'min': this.safeFloat (limits, 'limit-order-must-greater-than'), - 'max': this.safeFloat (limits, 'limit-order-must-less-than'), + 'min': this.safeNumber (limits, 'limit-order-must-greater-than'), + 'max': this.safeNumber (limits, 'limit-order-must-less-than'), }, }, }; @@ -351,9 +356,9 @@ module.exports = class huobipro extends Exchange { }; const maker = (base === 'OMG') ? 0 : 0.2 / 100; const taker = (base === 'OMG') ? 0 : 0.2 / 100; - const minAmount = this.safeFloat (market, 'min-order-amt', Math.pow (10, -precision['amount'])); - const maxAmount = this.safeFloat (market, 'max-order-amt'); - const minCost = this.safeFloat (market, 'min-order-value', 0); + const minAmount = this.safeNumber (market, 'min-order-amt', Math.pow (10, -precision['amount'])); + const maxAmount = this.safeNumber (market, 'max-order-amt'); + const minCost = this.safeNumber (market, 'min-order-value', 0); const state = this.safeString (market, 'state'); const active = (state === 'online'); result.push ({ @@ -432,24 +437,24 @@ module.exports = class huobipro extends Exchange { let askVolume = undefined; if ('bid' in ticker) { if (Array.isArray (ticker['bid'])) { - bid = this.safeFloat (ticker['bid'], 0); - bidVolume = this.safeFloat (ticker['bid'], 1); + bid = this.safeNumber (ticker['bid'], 0); + bidVolume = this.safeNumber (ticker['bid'], 1); } else { - bid = this.safeFloat (ticker, 'bid'); + bid = this.safeNumber (ticker, 'bid'); bidVolume = this.safeValue (ticker, 'bidSize'); } } if ('ask' in ticker) { if (Array.isArray (ticker['ask'])) { - ask = this.safeFloat (ticker['ask'], 0); - askVolume = this.safeFloat (ticker['ask'], 1); + ask = this.safeNumber (ticker['ask'], 0); + askVolume = this.safeNumber (ticker['ask'], 1); } else { - ask = this.safeFloat (ticker, 'ask'); + ask = this.safeNumber (ticker, 'ask'); askVolume = this.safeValue (ticker, 'askSize'); } } - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -460,15 +465,15 @@ module.exports = class huobipro extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -557,7 +562,7 @@ module.exports = class huobipro extends Exchange { // } // const ticker = this.parseTicker (response['tick'], market); - const timestamp = this.safeValue (response, 'ts'); + const timestamp = this.safeInteger (response, 'ts'); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); return ticker; @@ -626,21 +631,18 @@ module.exports = class huobipro extends Exchange { type = typeParts[1]; } const takerOrMaker = this.safeString (trade, 'role'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'filled-amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'filled-amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - let feeCost = this.safeFloat (trade, 'filled-fees'); + let feeCost = this.safeNumber (trade, 'filled-fees'); let feeCurrency = undefined; if (market !== undefined) { feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-currency')); } - const filledPoints = this.safeFloat (trade, 'filled-points'); + const filledPoints = this.safeNumber (trade, 'filled-points'); if (filledPoints !== undefined) { if ((feeCost === undefined) || (feeCost === 0.0)) { feeCost = filledPoints; @@ -754,11 +756,11 @@ module.exports = class huobipro extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -855,11 +857,11 @@ module.exports = class huobipro extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'deposit-min-amount'), + 'min': this.safeNumber (currency, 'deposit-min-amount'), 'max': Math.pow (10, precision), }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw-min-amount'), + 'min': this.safeNumber (currency, 'withdraw-min-amount'), 'max': Math.pow (10, precision), }, }, @@ -890,14 +892,14 @@ module.exports = class huobipro extends Exchange { account = this.account (); } if (balance['type'] === 'trade') { - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); } if (balance['type'] === 'frozen') { - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrdersByStates (states, symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1072,28 +1074,14 @@ module.exports = class huobipro extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (order, 'created-at'); - let amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount - if ((type === 'market') && (side === 'buy')) { - amount = (status === 'closed') ? filled : undefined; - } - let price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - const cost = this.safeFloat2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - // if cost is defined and filled is not zero - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - const feeCost = this.safeFloat2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees + const cost = this.safeNumber2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo + const feeCost = this.safeNumber2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -1105,7 +1093,7 @@ module.exports = class huobipro extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1119,15 +1107,15 @@ module.exports = class huobipro extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1201,26 +1189,82 @@ module.exports = class huobipro extends Exchange { }); } - currencyToPrecision (currency, fee) { - return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); + async cancelOrders (ids, symbol = undefined, params = {}) { + await this.loadMarkets (); + const clientOrderIds = this.safeValue2 (params, 'clientOrderIds', 'client-order-ids'); + params = this.omit (params, [ 'clientOrderIds', 'client-order-ids' ]); + const request = {}; + if (clientOrderIds === undefined) { + request['order-ids'] = ids; + } else { + request['client-order-ids'] = clientOrderIds; + } + const response = await this.privatePostOrderOrdersBatchcancel (this.extend (request, params)); + // + // { + // "status": "ok", + // "data": { + // "success": [ + // "5983466" + // ], + // "failed": [ + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "first" + // }, + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "second" + // }, + // { + // "err-msg": "The record is not found.", + // "order-id": "", + // "err-code": "base-not-found", + // "client-order-id": "third" + // } + // ] + // } + // } + // + return response; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (market[key], cost)), + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'account-id' string false NA The account id used for this cancel Refer to GET /v1/account/accounts + // 'symbol': market['id'], // a list of comma-separated symbols, all symbols by default + // 'types' 'string', buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok + // 'side': 'buy', // or 'sell' + // 'size': 100, // the number of orders to cancel 1-100 }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.privatePostOrderOrdersBatchCancelOpenOrders (this.extend (request, params)); + // + // { + // code: 200, + // data: { + // "success-count": 2, + // "failed-count": 0, + // "next-id": 5454600 + // } + // } + // + return response; + } + + currencyToPrecision (currency, fee) { + return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); } parseDepositAddress (depositAddress, currency = undefined) { @@ -1362,7 +1406,7 @@ module.exports = class huobipro extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const tag = this.safeString (transaction, 'address-tag'); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -1375,7 +1419,7 @@ module.exports = class huobipro extends Exchange { 'address': this.safeString (transaction, 'address'), 'tag': tag, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ice3x.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ice3x.js deleted file mode 100644 index f228076d1..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ice3x.js +++ /dev/null @@ -1,495 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class ice3x extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'ice3x', - 'name': 'ICE3X', - 'countries': [ 'ZA' ], // South Africa - 'rateLimit': 1000, - 'version': 'v1', - 'has': { - 'cancelOrder': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchCurrencies': true, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTrades': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg', - 'api': 'https://ice3x.com/api', - 'www': 'https://ice3x.com', // 'https://ice3x.co.za', - 'doc': 'https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017', - 'fees': [ - 'https://help.ice3.com/support/solutions/articles/11000033293-trading-fees', - 'https://help.ice3.com/support/solutions/articles/11000033288-fees-explained', - 'https://help.ice3.com/support/solutions/articles/11000008131-what-are-your-fiat-deposit-and-withdrawal-fees-', - 'https://help.ice3.com/support/solutions/articles/11000033289-deposit-fees', - ], - 'referral': 'https://ice3x.com?ref=14341802', - }, - 'api': { - 'public': { - 'get': [ - 'currency/list', - 'currency/info', - 'pair/list', - 'pair/info', - 'stats/marketdepthfull', - 'stats/marketdepthbtcav', - 'stats/marketdepth', - 'orderbook/info', - 'trade/list', - 'trade/info', - ], - }, - 'private': { - 'post': [ - 'balance/list', - 'balance/info', - 'order/new', - 'order/cancel', - 'order/list', - 'order/info', - 'trade/list', - 'trade/info', - 'transaction/list', - 'transaction/info', - 'invoice/list', - 'invoice/info', - 'invoice/pdf', - ], - }, - }, - 'fees': { - 'trading': { - 'maker': 0.005, - 'taker': 0.005, - }, - }, - 'precision': { - 'amount': 8, - 'price': 8, - }, - }); - } - - async fetchCurrencies (params = {}) { - const response = await this.publicGetCurrencyList (params); - const currencies = response['response']['entities']; - const precision = this.precision['amount']; - const result = {}; - for (let i = 0; i < currencies.length; i++) { - const currency = currencies[i]; - const id = this.safeString (currency, 'currency_id'); - const currencyId = this.safeString (currency, 'iso'); - const code = this.safeCurrencyCode (currencyId); - result[code] = { - 'id': id, - 'code': code, - 'name': currency['name'], - 'active': true, - 'precision': precision, - 'limits': { - 'amount': { - 'min': undefined, - 'max': Math.pow (10, precision), - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': Math.pow (10, precision), - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - }, - 'info': currency, - 'fee': undefined, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - if (this.currencies_by_id === undefined) { - this.currencies = await this.fetchCurrencies (); - this.currencies_by_id = this.indexBy (this.currencies, 'id'); - } - const response = await this.publicGetPairList (params); - const markets = this.safeValue (response['response'], 'entities'); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = this.safeString (market, 'pair_id'); - const baseId = this.safeString (market, 'currency_id_from'); - const quoteId = this.safeString (market, 'currency_id_to'); - const baseCurrency = this.currencies_by_id[baseId]; - const quoteCurrency = this.currencies_by_id[quoteId]; - const base = baseCurrency['code']; - const quote = quoteCurrency['code']; - const symbol = base + '/' + quote; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': undefined, - 'info': market, - 'precision': this.precision, - 'limits': this.limits, - }); - } - return result; - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.milliseconds (); - const symbol = market['symbol']; - const last = this.safeFloat (ticker, 'last_price'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'max_bid'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'min_ask'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'vol'), - 'info': ticker, - }; - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetStatsMarketdepthfull (this.extend (request, params)); - const ticker = this.safeValue (response['response'], 'entity'); - return this.parseTicker (ticker, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetStatsMarketdepthfull (params); - const tickers = this.safeValue (response['response'], 'entities'); - const result = {}; - for (let i = 0; i < tickers.length; i++) { - const ticker = tickers[i]; - const marketId = this.safeString (ticker, 'pair_id'); - const market = this.safeValue (this.marketsById, marketId); - if (market !== undefined) { - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); - } - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'pair_id': this.marketId (symbol), - }; - if (limit !== undefined) { - const type = this.safeString (params, 'type'); - if ((type !== 'ask') && (type !== 'bid')) { - // eslint-disable-next-line quotes - throw new ArgumentsRequired (this.id + " fetchOrderBook() requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit"); - } else { - request['items_per_page'] = limit; - } - } - const response = await this.publicGetOrderbookInfo (this.extend (request, params)); - const orderbook = this.safeValue (response['response'], 'entities'); - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.safeTimestamp (trade, 'created'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } - const type = 'limit'; - const side = this.safeString (trade, 'type'); - const id = this.safeString (trade, 'trade_id'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'id': id, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': type, - 'side': side, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetTradeList (this.extend (request, params)); - const trades = this.safeValue (response['response'], 'entities'); - return this.parseTrades (trades, market, since, limit); - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostBalanceList (params); - const result = { 'info': response }; - const balances = this.safeValue (response['response'], 'entities', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - // currency ids are numeric strings - const currencyId = this.safeString (balance, 'currency_id'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseOrder (order, market = undefined) { - const pairId = this.safeInteger (order, 'pair_id'); - let symbol = undefined; - if (pairId && !market && (pairId in this.marketsById)) { - market = this.marketsById[pairId]; - symbol = market['symbol']; - } - const timestamp = this.safeTimestamp (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - let status = this.safeInteger (order, 'active'); - let remaining = this.safeFloat (order, 'remaining'); - let filled = undefined; - if (status === 1) { - status = 'open'; - } else { - status = 'closed'; - remaining = 0; - filled = amount; - } - let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - }; - if (market !== undefined) { - fee['currency'] = market['quote']; - } - } - return { - 'id': this.safeString (order, 'order_id'), - 'clientOrderId': undefined, - 'datetime': this.iso8601 (timestamp), - 'timestamp': timestamp, - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': 'limit', - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': this.safeString (order, 'type'), - 'price': price, - 'stopPrice': undefined, - 'cost': undefined, - 'amount': amount, - 'filled': filled, - 'remaining': remaining, - 'trades': undefined, - 'fee': fee, - 'info': order, - 'average': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - 'type': side, - 'amount': amount, - 'price': price, - }; - const response = await this.privatePostOrderNew (this.extend (request, params)); - const order = this.parseOrder ({ - 'order_id': response['response']['entity']['order_id'], - 'created': this.seconds (), - 'active': 1, - 'type': side, - 'price': price, - 'volume': amount, - 'remaining': amount, - 'info': response, - }, market); - return order; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - const request = { - 'order_id': id, - }; - return await this.privatePostOrderCancel (this.extend (request, params)); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'order _id': id, - }; - const response = await this.privatePostOrderInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const order = this.safeValue (data, 'entity'); - return this.parseOrder (order); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.privatePostOrderList (params); - const data = this.safeValue (response, 'response', {}); - const orders = this.safeValue (data, 'entities', []); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - return this.parseOrders (orders, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - if (limit !== undefined) { - request['items_per_page'] = limit; - } - if (since !== undefined) { - request['date_from'] = parseInt (since / 1000); - } - const response = await this.privatePostTradeList (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const trades = this.safeValue (data, 'entities', []); - return this.parseTrades (trades, market, since, limit); - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency_id': currency['id'], - }; - const response = await this.privatePostBalanceInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const balance = this.safeValue (data, 'entity', {}); - const address = this.safeString (balance, 'address'); - const status = address ? 'ok' : 'none'; - return { - 'currency': code, - 'address': address, - 'tag': undefined, - 'status': status, - 'info': response, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/' + this.version + '/' + path; - if (api === 'public') { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } - } else { - this.checkRequiredCredentials (); - body = this.urlencode (this.extend ({ - 'nonce': this.nonce (), - }, params)); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const response = await this.fetch2 (path, api, method, params, headers, body); - const errors = this.safeValue (response, 'errors'); - const data = this.safeValue (response, 'response'); - if (errors || !data) { - const authErrorKeys = [ 'Key', 'user_id', 'Sign' ]; - for (let i = 0; i < authErrorKeys.length; i++) { - const errorKey = authErrorKeys[i]; - const errorMessage = this.safeString (errors, errorKey); - if (!errorMessage) { - continue; - } - if (errorKey === 'user_id' && errorMessage.indexOf ('authorization') < 0) { - continue; - } - throw new AuthenticationError (errorMessage); - } - throw new ExchangeError (this.json (errors)); - } - return response; - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/idex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/idex.js index 7d52a5286..c3c14d981 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/idex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/idex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { PAD_WITH_ZERO } = require ('./base/functions/number'); const { InvalidOrder, InsufficientFunds, ExchangeError, ExchangeNotAvailable, DDoSProtection, BadRequest, NotSupported, InvalidAddress, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -241,14 +242,6 @@ module.exports = class idex extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // { // market: 'DIL-ETH', @@ -268,16 +261,16 @@ module.exports = class idex extends Exchange { // } const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'baseVolume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'baseVolume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'open'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const close = this.safeFloat (ticker, 'close'); - const ask = this.safeFloat (ticker, 'ask'); - const bid = this.safeFloat (ticker, 'bid'); - let percentage = this.safeFloat (ticker, 'percentChange'); + const open = this.safeNumber (ticker, 'open'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const close = this.safeNumber (ticker, 'close'); + const ask = this.safeNumber (ticker, 'ask'); + const bid = this.safeNumber (ticker, 'bid'); + let percentage = this.safeNumber (ticker, 'percentChange'); if (percentage !== undefined) { percentage = 1 + percentage / 100; } @@ -353,11 +346,11 @@ module.exports = class idex extends Exchange { // sequence: 3853 // } const timestamp = this.safeInteger (ohlcv, 'start'); - const open = this.safeFloat (ohlcv, 'open'); - const high = this.safeFloat (ohlcv, 'high'); - const low = this.safeFloat (ohlcv, 'low'); - const close = this.safeFloat (ohlcv, 'close'); - const volume = this.safeFloat (ohlcv, 'volume'); + const open = this.safeNumber (ohlcv, 'open'); + const high = this.safeNumber (ohlcv, 'high'); + const low = this.safeNumber (ohlcv, 'low'); + const close = this.safeNumber (ohlcv, 'close'); + const volume = this.safeNumber (ohlcv, 'volume'); return [ timestamp, open, high, low, close, volume ]; } @@ -419,9 +412,14 @@ module.exports = class idex extends Exchange { // txStatus: 'mined' // } const id = this.safeString (trade, 'fillId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'quoteQuantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteQuantity'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const timestamp = this.safeInteger (trade, 'time'); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); @@ -430,7 +428,7 @@ module.exports = class idex extends Exchange { const oppositeSide = (makerSide === 'buy') ? 'sell' : 'buy'; const side = this.safeString (trade, 'side', oppositeSide); const takerOrMaker = this.safeString (trade, 'liquidity', 'taker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); @@ -503,8 +501,8 @@ module.exports = class idex extends Exchange { const result = []; for (let i = 0; i < bookSide.length; i++) { const order = bookSide[i]; - const price = this.safeFloat (order, 0); - const amount = this.safeFloat (order, 1); + const price = this.safeNumber (order, 0); + const amount = this.safeNumber (order, 1); const orderCount = this.safeInteger (order, 2); result.push ([ price, amount, orderCount ]); } @@ -591,16 +589,13 @@ module.exports = class idex extends Exchange { const entry = response[i]; const currencyId = this.safeString (entry, 'asset'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (entry, 'quantity'); - const free = this.safeFloat (entry, 'availableForTrade'); - const used = this.safeFloat (entry, 'locked'); - result[code] = { - 'free': free, - 'used': used, - 'total': total, - }; + const account = this.account (); + account['total'] = this.safeString (entry, 'quantity'); + account['free'] = this.safeString (entry, 'availableForTrade'); + account['used'] = this.safeString (entry, 'locked'); + result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -821,10 +816,10 @@ module.exports = class idex extends Exchange { const symbol = this.safeSymbol (marketId, market, '-'); const trades = this.parseTrades (fills, market); const type = this.safeString (order, 'type'); - const amount = this.safeFloat (order, 'originalQuantity'); - const filled = this.safeFloat (order, 'executedQuantity'); - const average = this.safeFloat (order, 'avgExecutionPrice'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'originalQuantity'); + const filled = this.safeNumber (order, 'executedQuantity'); + const average = this.safeNumber (order, 'avgExecutionPrice'); + const price = this.safeNumber (order, 'price'); const rawStatus = this.safeString (order, 'status'); const status = this.parseOrderStatus (rawStatus); const fee = { @@ -933,7 +928,7 @@ module.exports = class idex extends Exchange { throw new NotSupported (this.id + ' quoteOrderQuantity is not supported for ' + type + ' orders, only supported for market orders'); } amountEnum = 1; - amount = this.safeFloat (params, 'quoteOrderQuantity'); + amount = this.safeNumber (params, 'quoteOrderQuantity'); } const sideEnum = (side === 'buy') ? 0 : 1; const walletBytes = this.remove0xPrefix (this.walletAddress); @@ -1236,13 +1231,13 @@ module.exports = class idex extends Exchange { } const id = this.safeString2 (transaction, 'depositId', 'withdrawId'); const code = this.safeCurrencyCode (this.safeString (transaction, 'asset'), currency); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const txid = this.safeString (transaction, 'txId'); const timestamp = this.safeInteger (transaction, 'txTime'); let fee = undefined; if ('fee' in transaction) { fee = { - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), 'currency': 'ETH', }; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/independentreserve.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/independentreserve.js index 119a216d5..86dcb348b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/independentreserve.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/independentreserve.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -126,11 +127,11 @@ module.exports = class independentreserve extends Exchange { const currencyId = this.safeString (balance, 'CurrencyCode'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'AvailableBalance'); - account['total'] = this.safeFloat (balance, 'TotalBalance'); + account['free'] = this.safeString (balance, 'AvailableBalance'); + account['total'] = this.safeString (balance, 'TotalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -151,16 +152,16 @@ module.exports = class independentreserve extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'LastPrice'); + const last = this.safeNumber (ticker, 'LastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'DayHighestPrice'), - 'low': this.safeFloat (ticker, 'DayLowestPrice'), - 'bid': this.safeFloat (ticker, 'CurrentHighestBidPrice'), + 'high': this.safeNumber (ticker, 'DayHighestPrice'), + 'low': this.safeNumber (ticker, 'DayLowestPrice'), + 'bid': this.safeNumber (ticker, 'CurrentHighestBidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'CurrentLowestOfferPrice'), + 'ask': this.safeNumber (ticker, 'CurrentLowestOfferPrice'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -169,8 +170,8 @@ module.exports = class independentreserve extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'DayAvgPrice'), - 'baseVolume': this.safeFloat (ticker, 'DayVolumeXbtInSecondaryCurrrency'), + 'average': this.safeNumber (ticker, 'DayAvgPrice'), + 'baseVolume': this.safeNumber (ticker, 'DayVolumeXbtInSecondaryCurrrency'), 'quoteVolume': undefined, 'info': ticker, }; @@ -249,20 +250,10 @@ module.exports = class independentreserve extends Exchange { orderType = 'limit'; } const timestamp = this.parse8601 (this.safeString (order, 'CreatedTimestampUtc')); - const amount = this.safeFloat2 (order, 'VolumeOrdered', 'Volume'); - let filled = this.safeFloat (order, 'VolumeFilled'); - let remaining = this.safeFloat (order, 'Outstanding'); - if (filled === undefined) { - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (0, amount - remaining); - } - } - if (remaining === undefined) { - if ((filled !== undefined) && (amount !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const feeRate = this.safeFloat (order, 'FeePercent'); + const amount = this.safeNumber2 (order, 'VolumeOrdered', 'Volume'); + const filled = this.safeNumber (order, 'VolumeFilled'); + const remaining = this.safeNumber (order, 'Outstanding'); + const feeRate = this.safeNumber (order, 'FeePercent'); let feeCost = undefined; if (feeRate !== undefined) { feeCost = feeRate * filled; @@ -274,10 +265,10 @@ module.exports = class independentreserve extends Exchange { }; const id = this.safeString (order, 'OrderGuid'); const status = this.parseOrderStatus (this.safeString (order, 'Status')); - const cost = this.safeFloat (order, 'Value'); - const average = this.safeFloat (order, 'AvgPrice'); - const price = this.safeFloat (order, 'Price', average); - return { + const cost = this.safeNumber (order, 'Value'); + const average = this.safeNumber (order, 'AvgPrice'); + const price = this.safeNumber (order, 'Price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -299,7 +290,7 @@ module.exports = class independentreserve extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -387,14 +378,11 @@ module.exports = class independentreserve extends Exchange { const timestamp = this.parse8601 (trade['TradeTimestampUtc']); const id = this.safeString (trade, 'TradeGuid'); const orderId = this.safeString (trade, 'OrderGuid'); - const price = this.safeFloat2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); - const amount = this.safeFloat2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); + const amountString = this.safeString2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const baseId = this.safeString (trade, 'PrimaryCurrencyCode'); const quoteId = this.safeString (trade, 'SecondaryCurrencyCode'); let marketId = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/indodax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/indodax.js index f1cc33732..05972a887 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/indodax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/indodax.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, InvalidOrder, OrderNotFound, AuthenticationError, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,7 +165,7 @@ module.exports = class indodax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const taker = this.safeFloat (market, 'trade_fee_percent'); + const taker = this.safeNumber (market, 'trade_fee_percent'); const isMaintenance = this.safeInteger (market, 'is_maintenance'); const active = (isMaintenance) ? false : true; const pricePrecision = this.safeInteger (market, 'price_round'); @@ -174,11 +175,11 @@ module.exports = class indodax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'trade_min_traded_currency'), + 'min': this.safeNumber (market, 'trade_min_traded_currency'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'trade_min_base_currency'), + 'min': this.safeNumber (market, 'trade_min_base_currency'), 'max': undefined, }, 'cost': { @@ -216,11 +217,11 @@ module.exports = class indodax extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (used, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (used, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -257,16 +258,16 @@ module.exports = class indodax extends Exchange { const timestamp = this.safeTimestamp (ticker, 'server_time'); const baseVolume = 'vol_' + market['baseId'].toLowerCase (); const quoteVolume = 'vol_' + market['quoteId'].toLowerCase (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -276,8 +277,8 @@ module.exports = class indodax extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, baseVolume), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, baseVolume), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -291,14 +292,11 @@ module.exports = class indodax extends Exchange { } const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -353,7 +351,7 @@ module.exports = class indodax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status', 'open')); let symbol = undefined; let cost = undefined; - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let amount = undefined; let remaining = undefined; let filled = undefined; @@ -367,18 +365,18 @@ module.exports = class indodax extends Exchange { if ((market['baseId'] === 'idr') && ('remain_rp' in order)) { baseId = 'rp'; } - cost = this.safeFloat (order, 'order_' + quoteId); + cost = this.safeNumber (order, 'order_' + quoteId); if (cost) { amount = cost / price; - const remainingCost = this.safeFloat (order, 'remain_' + quoteId); + const remainingCost = this.safeNumber (order, 'remain_' + quoteId); if (remainingCost !== undefined) { remaining = remainingCost / price; filled = amount - remaining; } } else { - amount = this.safeFloat (order, 'order_' + baseId); + amount = this.safeNumber (order, 'order_' + baseId); cost = price * amount; - remaining = this.safeFloat (order, 'remain_' + baseId); + remaining = this.safeNumber (order, 'remain_' + baseId); filled = amount - remaining; } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/itbit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/itbit.js index 552bb0de5..a46080ccc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/itbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/itbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -114,25 +115,25 @@ module.exports = class itbit extends Exchange { throw new ExchangeError (this.id + ' fetchTicker returned a bad response: ' + this.json (ticker)); } const timestamp = this.parse8601 (serverTimeUTC); - const vwap = this.safeFloat (ticker, 'vwap24h'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); + const vwap = this.safeNumber (ticker, 'vwap24h'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'openToday'), + 'open': this.safeNumber (ticker, 'openToday'), 'close': last, 'last': last, 'previousClose': undefined, @@ -179,23 +180,20 @@ module.exports = class itbit extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const side = this.safeString (trade, 'direction'); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'commissionPaid'); + let feeCost = this.safeNumber (trade, 'commissionPaid'); const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - let rebatesApplied = this.safeFloat (trade, 'rebatesApplied'); + let rebatesApplied = this.safeNumber (trade, 'rebatesApplied'); if (rebatesApplied !== undefined) { rebatesApplied = -rebatesApplied; } const rebateCurrencyId = this.safeString (trade, 'rebateCurrency'); const rebateCurrency = this.safeCurrencyCode (rebateCurrencyId); - const price = this.safeFloat2 (trade, 'price', 'rate'); - const amount = this.safeFloat2 (trade, 'currency1Amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'price', 'rate'); + const amountString = this.safeString2 (trade, 'currency1Amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; const marketId = this.safeString (trade, 'instrument'); if (marketId !== undefined) { @@ -317,7 +315,7 @@ module.exports = class itbit extends Exchange { 'txid': txnHash, 'type': transactionType, 'status': status, - 'amount': this.safeFloat (item, 'amount'), + 'amount': this.safeNumber (item, 'amount'), 'fee': undefined, 'info': item, }); @@ -417,11 +415,11 @@ module.exports = class itbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchWallets (params = {}) { @@ -512,26 +510,16 @@ module.exports = class itbit extends Exchange { const type = this.safeString (order, 'type'); const symbol = this.markets_by_id[order['instrument']]['symbol']; const timestamp = this.parse8601 (order['createdTime']); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'amountFilled'); - let remaining = undefined; - let cost = undefined; + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'amountFilled'); const fee = undefined; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'volumeWeightedAveragePrice'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'volumeWeightedAveragePrice'); const clientOrderId = this.safeString (order, 'clientOrderIdentifier'); const id = this.safeString (order, 'id'); const postOnlyString = this.safeString (order, 'postOnly'); const postOnly = (postOnlyString === 'True'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -546,15 +534,15 @@ module.exports = class itbit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, // 'trades': this.parseTrades (order['trades'], market), 'trades': undefined, - }; + }); } nonce () { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kraken.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kraken.js index 198ee4cf8..514ed0094 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kraken.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kraken.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeNotAvailable, ArgumentsRequired, PermissionDenied, AuthenticationError, ExchangeError, OrderNotFound, DDoSProtection, InvalidNonce, InsufficientFunds, CancelPending, InvalidOrder, InvalidAddress, RateLimitExceeded } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -297,26 +298,38 @@ module.exports = class kraken extends Exchange { // } // } // - const keys = Object.keys (response['result']); + const markets = this.safeValue (response, 'result', {}); + const keys = Object.keys (markets); let result = []; for (let i = 0; i < keys.length; i++) { const id = keys[i]; - const market = response['result'][id]; - const baseId = market['base']; - const quoteId = market['quote']; + const market = markets[id]; + const baseId = this.safeString (market, 'base'); + const quoteId = this.safeString (market, 'quote'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const darkpool = id.indexOf ('.d') >= 0; - const symbol = darkpool ? market['altname'] : (base + '/' + quote); + const altname = this.safeString (market, 'altname'); + const symbol = darkpool ? altname : (base + '/' + quote); + const makerFees = this.safeValue (market, 'fees_maker', []); + const firstMakerFee = this.safeValue (makerFees, 0, []); + const firstMakerFeeRate = this.safeNumber (firstMakerFee, 1); let maker = undefined; - if ('fees_maker' in market) { - maker = parseFloat (market['fees_maker'][0][1]) / 100; + if (firstMakerFeeRate !== undefined) { + maker = parseFloat (firstMakerFeeRate) / 100; + } + const takerFees = this.safeValue (market, 'fees', []); + const firstTakerFee = this.safeValue (takerFees, 0, []); + const firstTakerFeeRate = this.safeNumber (firstTakerFee, 1); + let taker = undefined; + if (firstTakerFeeRate !== undefined) { + taker = parseFloat (firstTakerFeeRate) / 100; } const precision = { - 'amount': market['lot_decimals'], - 'price': market['pair_decimals'], + 'amount': this.safeInteger (market, 'lot_decimals'), + 'price': this.safeInteger (market, 'pair_decimals'), }; - const minAmount = this.safeFloat (market, 'ordermin'); + const minAmount = this.safeNumber (market, 'ordermin'); result.push ({ 'id': id, 'symbol': symbol, @@ -328,7 +341,7 @@ module.exports = class kraken extends Exchange { 'info': market, 'altname': market['altname'], 'maker': maker, - 'taker': parseFloat (market['fees'][0][1]) / 100, + 'taker': taker, 'active': true, 'precision': precision, 'limits': { @@ -451,7 +464,7 @@ module.exports = class kraken extends Exchange { await this.loadMarkets (); this.checkRequiredCredentials (); const response = await this.privatePostTradeVolume (params); - const tradedVolume = this.safeFloat (response['result'], 'volume'); + const tradedVolume = this.safeNumber (response['result'], 'volume'); const tiers = this.fees['trading']['tiers']; let taker = tiers['taker'][1]; let maker = tiers['maker'][1]; @@ -473,8 +486,8 @@ module.exports = class kraken extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); const timestamp = this.safeInteger (bidask, 2); return [ price, amount, timestamp ]; } @@ -512,7 +525,14 @@ module.exports = class kraken extends Exchange { // } // const result = this.safeValue (response, 'result', {}); - const orderbook = this.safeValue (result, market['id']); + let orderbook = this.safeValue (result, market['id']); + // sometimes kraken returns wsname instead of market id + // https://github.com/ccxt/ccxt/issues/8662 + const marketInfo = this.safeValue (market, 'info', {}); + const wsName = this.safeValue (marketInfo, 'wsname'); + if (wsName !== undefined) { + orderbook = this.safeValue (result, wsName, orderbook); + } return this.parseOrderBook (orderbook); } @@ -540,7 +560,7 @@ module.exports = class kraken extends Exchange { 'ask': parseFloat (ticker['a'][0]), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'o'), + 'open': this.safeNumber (ticker, 'o'), 'close': last, 'last': last, 'previousClose': undefined, @@ -611,11 +631,11 @@ module.exports = class kraken extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 6), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 6), ]; } @@ -682,24 +702,24 @@ module.exports = class kraken extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'asset'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); } else { direction = 'in'; } - const time = this.safeFloat (item, 'time'); + const time = this.safeNumber (item, 'time'); let timestamp = undefined; if (time !== undefined) { timestamp = parseInt (time * 1000); } const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -823,9 +843,8 @@ module.exports = class kraken extends Exchange { let timestamp = undefined; let side = undefined; let type = undefined; - let price = undefined; - let amount = undefined; - let cost = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; let orderId = undefined; let fee = undefined; @@ -834,8 +853,8 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 2); side = (trade[3] === 's') ? 'sell' : 'buy'; type = (trade[4] === 'l') ? 'limit' : 'market'; - price = this.safeFloat (trade, 0); - amount = this.safeFloat (trade, 1); + priceString = this.safeString (trade, 0); + amountString = this.safeString (trade, 1); const tradeLength = trade.length; if (tradeLength > 6) { id = this.safeString (trade, 6); // artificially added as per #1794 @@ -856,15 +875,15 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 'time'); side = this.safeString (trade, 'type'); type = this.safeString (trade, 'ordertype'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'vol'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'vol'); if ('fee' in trade) { let currency = undefined; if (market !== undefined) { currency = market['quote']; } fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': currency, }; } @@ -872,11 +891,9 @@ module.exports = class kraken extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': orderId, @@ -951,10 +968,10 @@ module.exports = class kraken extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -983,15 +1000,15 @@ module.exports = class kraken extends Exchange { if (type === 'limit') { request['price'] = this.priceToPrecision (symbol, price); } else if ((type === 'stop-loss') || (type === 'take-profit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice', price); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice', price); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument or a price/stopPrice parameter for a ' + type + ' order'); } else { request['price'] = this.priceToPrecision (symbol, stopPrice); } } else if ((type === 'stop-loss-limit') || (type === 'take-profit-limit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice'); - const limitPrice = this.safeFloat (params, 'price2'); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice'); + const limitPrice = this.safeNumber (params, 'price2'); const stopPriceDefined = (stopPrice !== undefined); const limitPriceDefined = (limitPrice !== undefined); if (stopPriceDefined && limitPriceDefined) { @@ -1100,10 +1117,10 @@ module.exports = class kraken extends Exchange { if (orderDescription !== undefined) { const parts = orderDescription.split (' '); side = this.safeString (parts, 0); - amount = this.safeFloat (parts, 1); + amount = this.safeNumber (parts, 1); marketId = this.safeString (parts, 2); type = this.safeString (parts, 4); - price = this.safeFloat (parts, 5); + price = this.safeNumber (parts, 5); } side = this.safeString (description, 'type', side); type = this.safeString (description, 'ordertype', type); @@ -1117,27 +1134,23 @@ module.exports = class kraken extends Exchange { market = this.getDelistedMarketById (marketId); } const timestamp = this.safeTimestamp (order, 'opentm'); - amount = this.safeFloat (order, 'vol', amount); - const filled = this.safeFloat (order, 'vol_exec'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = amount - filled; - } + amount = this.safeNumber (order, 'vol', amount); + const filled = this.safeNumber (order, 'vol_exec'); let fee = undefined; - const cost = this.safeFloat (order, 'cost'); - price = this.safeFloat (description, 'price', price); + const cost = this.safeNumber (order, 'cost'); + price = this.safeNumber (description, 'price', price); if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (description, 'price2'); + price = this.safeNumber (description, 'price2'); } if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (order, 'price', price); + price = this.safeNumber (order, 'price', price); } - const average = this.safeFloat (order, 'price'); + const average = this.safeNumber (order, 'price'); if (market !== undefined) { symbol = market['symbol']; if ('fee' in order) { const flags = order['oflags']; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); fee = { 'cost': feeCost, 'rate': undefined, @@ -1161,8 +1174,8 @@ module.exports = class kraken extends Exchange { if (rawTrades !== undefined) { trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id }); } - const stopPrice = this.safeFloat (order, 'stopprice'); - return { + const stopPrice = this.safeNumber (order, 'stopprice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -1181,10 +1194,10 @@ module.exports = class kraken extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1534,10 +1547,10 @@ module.exports = class kraken extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const address = this.safeString (transaction, 'info'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.safeString (transaction, 'type'); // injected from the outside - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost === undefined) { if (type === 'deposit') { feeCost = 0; @@ -1714,7 +1727,7 @@ module.exports = class kraken extends Exchange { throw new ExchangeError (this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)"); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { // 'txid': 'comma delimited list of transaction ids to restrict output to', diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kucoin.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kucoin.js index bcb058989..0b5aca5af 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kucoin.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kucoin.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -45,6 +46,7 @@ module.exports = class kucoin extends Exchange { 'fetchTrades': true, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg', @@ -52,6 +54,7 @@ module.exports = class kucoin extends Exchange { 'api': { 'public': 'https://openapi-v2.kucoin.com', 'private': 'https://openapi-v2.kucoin.com', + 'futuresPrivate': 'https://api-futures.kucoin.com', }, 'test': { 'public': 'https://openapi-sandbox.kucoin.com', @@ -160,6 +163,15 @@ module.exports = class kucoin extends Exchange { 'stop-order/cancel', ], }, + 'futuresPrivate': { + 'get': [ + 'account-overview', + 'positions', + ], + 'post': [ + 'transfer-out', + ], + }, }, 'timeframes': { '1m': '1min', @@ -184,6 +196,7 @@ module.exports = class kucoin extends Exchange { 'order_not_exist_or_not_allow_to_cancel': InvalidOrder, // {"code":"400100","msg":"order_not_exist_or_not_allow_to_cancel"} 'Order size below the minimum requirement.': InvalidOrder, // {"code":"400100","msg":"Order size below the minimum requirement."} 'The withdrawal amount is below the minimum requirement.': ExchangeError, // {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."} + 'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, // {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"} '400': BadRequest, '401': AuthenticationError, '403': NotSupported, @@ -240,9 +253,7 @@ module.exports = class kucoin extends Exchange { 'version': 'v1', 'symbolSeparator': '-', 'fetchMyTradesMethod': 'private_get_fills', - 'fetchBalance': { - 'type': 'trade', // or 'main' - }, + 'fetchBalance': 'trade', // endpoint versions 'versions': { 'public': { @@ -262,6 +273,25 @@ module.exports = class kucoin extends Exchange { 'accounts/sub-transfer': 'v2', }, }, + 'futuresPrivate': { + 'GET': { + 'account-overview': 'v1', + 'positions': 'v1', + }, + 'POST': { + 'transfer-out': 'v2', + }, + }, + }, + 'accountsByType': { + 'trade': 'trade', + 'trading': 'trade', + 'margin': 'margin', + 'main': 'main', + 'futures': 'contract', + 'contract': 'contract', + 'pool': 'pool', + 'pool-x': 'pool', }, }, }); @@ -342,11 +372,11 @@ module.exports = class kucoin extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const active = this.safeValue (market, 'enableTrading'); - const baseMaxSize = this.safeFloat (market, 'baseMaxSize'); - const baseMinSize = this.safeFloat (market, 'baseMinSize'); - const quoteMaxSize = this.safeFloat (market, 'quoteMaxSize'); - const quoteMinSize = this.safeFloat (market, 'quoteMinSize'); - // const quoteIncrement = this.safeFloat (market, 'quoteIncrement'); + const baseMaxSize = this.safeNumber (market, 'baseMaxSize'); + const baseMinSize = this.safeNumber (market, 'baseMinSize'); + const quoteMaxSize = this.safeNumber (market, 'quoteMaxSize'); + const quoteMinSize = this.safeNumber (market, 'quoteMinSize'); + // const quoteIncrement = this.safeNumber (market, 'quoteIncrement'); const precision = { 'amount': this.precisionFromString (this.safeString (market, 'baseIncrement')), 'price': this.precisionFromString (this.safeString (market, 'priceIncrement')), @@ -357,7 +387,7 @@ module.exports = class kucoin extends Exchange { 'max': baseMaxSize, }, 'price': { - 'min': this.safeFloat (market, 'priceIncrement'), + 'min': this.safeNumber (market, 'priceIncrement'), 'max': quoteMaxSize / baseMinSize, }, 'cost': { @@ -408,7 +438,7 @@ module.exports = class kucoin extends Exchange { const precision = this.safeInteger (entry, 'precision'); const isWithdrawEnabled = this.safeValue (entry, 'isWithdrawEnabled', false); const isDepositEnabled = this.safeValue (entry, 'isDepositEnabled', false); - const fee = this.safeFloat (entry, 'withdrawalMinFee'); + const fee = this.safeNumber (entry, 'withdrawalMinFee'); const active = (isWithdrawEnabled && isDepositEnabled); result[code] = { 'id': id, @@ -475,7 +505,7 @@ module.exports = class kucoin extends Exchange { const response = await this.privateGetWithdrawalsQuotas (this.extend (request, params)); const data = response['data']; const withdrawFees = {}; - withdrawFees[code] = this.safeFloat (data, 'withdrawMinFee'); + withdrawFees[code] = this.safeNumber (data, 'withdrawMinFee'); return { 'info': response, 'withdraw': withdrawFees, @@ -522,35 +552,35 @@ module.exports = class kucoin extends Exchange { // "mark": 0 // } // - let percentage = this.safeFloat (ticker, 'changeRate'); + let percentage = this.safeNumber (ticker, 'changeRate'); if (percentage !== undefined) { percentage = percentage * 100; } - const last = this.safeFloat2 (ticker, 'last', 'lastTradedPrice'); + const last = this.safeNumber2 (ticker, 'last', 'lastTradedPrice'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'vol'); - const quoteVolume = this.safeFloat (ticker, 'volValue'); + const baseVolume = this.safeNumber (ticker, 'vol'); + const quoteVolume = this.safeNumber (ticker, 'volValue'); const vwap = this.vwap (baseVolume, quoteVolume); const timestamp = this.safeInteger2 (ticker, 'time', 'datetime'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'changePrice'), + 'change': this.safeNumber (ticker, 'changePrice'), 'percentage': percentage, - 'average': this.safeFloat (ticker, 'averagePrice'), + 'average': this.safeNumber (ticker, 'averagePrice'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -634,11 +664,11 @@ module.exports = class kucoin extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -836,16 +866,18 @@ module.exports = class kucoin extends Exchange { // 'marginMode': 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned // 'autoBorrow': false, // The system will first borrow you funds at the optimal interest rate and then place an order for you }; - if (type !== 'market') { - request['price'] = this.priceToPrecision (symbol, price); - request['size'] = this.amountToPrecision (symbol, amount); - } else { - if (this.safeValue (params, 'quoteAmount')) { - // used to create market order by quote amount - https://github.com/ccxt/ccxt/issues/4876 - request['funds'] = this.amountToPrecision (symbol, amount); + const quoteAmount = this.safeNumber2 (params, 'cost', 'funds'); + if (type === 'market') { + if (quoteAmount !== undefined) { + params = this.omit (params, [ 'cost', 'funds' ]); + // kucoin uses base precision even for quote values + request['funds'] = this.amountToPrecision (symbol, quoteAmount); } else { request['size'] = this.amountToPrecision (symbol, amount); } + } else { + request['price'] = this.priceToPrecision (symbol, price); + request['size'] = this.amountToPrecision (symbol, amount); } const response = await this.privatePostOrders (this.extend (request, params)); // @@ -879,8 +911,10 @@ module.exports = class kucoin extends Exchange { 'fee': undefined, 'trades': undefined, }; - if (!this.safeValue (params, 'quoteAmount')) { + if (quoteAmount === undefined) { order['amount'] = amount; + } else { + order['cost'] = quoteAmount; } return order; } @@ -1056,15 +1090,18 @@ module.exports = class kucoin extends Exchange { const type = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'createdAt'); const datetime = this.iso8601 (timestamp); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); + if (price === 0.0) { + // market orders + price = undefined; + } const side = this.safeString (order, 'side'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (order, 'fee'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'dealSize'); - const cost = this.safeFloat (order, 'dealFunds'); - const remaining = amount - filled; + const feeCost = this.safeNumber (order, 'fee'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'dealSize'); + const cost = this.safeNumber (order, 'dealFunds'); // bool const isActive = this.safeValue (order, 'isActive', false); const cancelExist = this.safeValue (order, 'cancelExist', false); @@ -1074,20 +1111,11 @@ module.exports = class kucoin extends Exchange { 'currency': feeCurrency, 'cost': feeCost, }; - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const clientOrderId = this.safeString (order, 'clientOid'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': orderId, 'clientOrderId': clientOrderId, 'symbol': symbol, @@ -1100,7 +1128,7 @@ module.exports = class kucoin extends Exchange { 'stopPrice': stopPrice, 'cost': cost, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'timestamp': timestamp, 'datetime': datetime, 'fee': fee, @@ -1109,7 +1137,7 @@ module.exports = class kucoin extends Exchange { 'lastTradeTimestamp': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1310,7 +1338,6 @@ module.exports = class kucoin extends Exchange { const id = this.safeString2 (trade, 'tradeId', 'id'); const orderId = this.safeString (trade, 'orderId'); const takerOrMaker = this.safeString (trade, 'liquidity'); - const amount = this.safeFloat2 (trade, 'size', 'amount'); let timestamp = this.safeInteger (trade, 'time'); if (timestamp !== undefined) { timestamp = parseInt (timestamp / 1000000); @@ -1321,10 +1348,13 @@ module.exports = class kucoin extends Exchange { timestamp = timestamp * 1000; } } - const price = this.safeFloat2 (trade, 'price', 'dealPrice'); + const priceString = this.safeString2 (trade, 'price', 'dealPrice'); + const amountString = this.safeString2 (trade, 'size', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const side = this.safeString (trade, 'side'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); let feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -1336,20 +1366,16 @@ module.exports = class kucoin extends Exchange { fee = { 'cost': feeCost, 'currency': feeCurrency, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } let type = this.safeString (trade, 'type'); if (type === 'match') { type = undefined; } - let cost = this.safeFloat2 (trade, 'funds', 'dealValue'); + let cost = this.safeNumber2 (trade, 'funds', 'dealValue'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'info': trade, @@ -1445,7 +1471,7 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); let address = this.safeString (transaction, 'address'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let txid = this.safeString (transaction, 'walletTxId'); if (txid !== undefined) { const txidParts = txid.split ('@'); @@ -1463,7 +1489,7 @@ module.exports = class kucoin extends Exchange { const rawStatus = this.safeString (transaction, 'status'); const status = this.parseTransactionStatus (rawStatus); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { let rate = undefined; if (amount !== undefined) { @@ -1644,45 +1670,180 @@ module.exports = class kucoin extends Exchange { async fetchBalance (params = {}) { await this.loadMarkets (); - let type = undefined; - const request = {}; - if ('type' in params) { - type = params['type']; - if (type !== undefined) { - request['type'] = type; - } - params = this.omit (params, 'type'); + const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'trade'); + const requestedType = this.safeString (params, 'type', defaultType); + const accountsByType = this.safeValue (this.options, 'accountsByType'); + const type = this.safeString (accountsByType, requestedType); + if (type === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' type must be one of ' + keys.join (', ')); + } + params = this.omit (params, 'type'); + if (type === 'contract') { + // futures api requires a futures apiKey + // only fetches one balance at a time + // by default it will only fetch the BTC balance of the futures account + // you can send 'currency' in params to fetch other currencies + // fetchBalance ({ 'type': 'futures', 'currency': 'USDT' }) + const response = await this.futuresPrivateGetAccountOverview (params); + // + // { + // code: '200000', + // data: { + // accountEquity: 0.00005, + // unrealisedPNL: 0, + // marginBalance: 0.00005, + // positionMargin: 0, + // orderMargin: 0, + // frozenFunds: 0, + // availableBalance: 0.00005, + // currency: 'XBT' + // } + // } + // + const data = this.safeValue (response, 'data'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (data, 'availableBalance'); + account['total'] = this.safeString (data, 'accountEquity'); + const result = { 'info': response }; + result[code] = account; + return this.parseBalance (result, false); } else { - const options = this.safeValue (this.options, 'fetchBalance', {}); - type = this.safeString (options, 'type', 'trade'); - } - const response = await this.privateGetAccounts (this.extend (request, params)); - // - // { - // "code":"200000", - // "data":[ - // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, - // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, - // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - const result = { 'info': response }; - for (let i = 0; i < data.length; i++) { - const balance = data[i]; - const balanceType = this.safeString (balance, 'type'); - if (balanceType === type) { - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'holds'); - result[code] = account; + const request = { + 'type': type, + }; + const response = await this.privateGetAccounts (this.extend (request, params)); + // + // { + // "code":"200000", + // "data":[ + // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, + // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, + // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + const result = { 'info': response }; + for (let i = 0; i < data.length; i++) { + const balance = data[i]; + const balanceType = this.safeString (balance, 'type'); + if (balanceType === type) { + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'holds'); + result[code] = account; + } } + return this.parseBalance (result, false); + } + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const requestedAmount = this.currencyToPrecision (code, amount); + const accountsById = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsById, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsById, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + if (fromId === 'contract') { + if (toId !== 'main') { + throw new ExchangeError (this.id + ' only supports transferring from futures account to main account'); + } + const request = { + 'currency': currency['id'], + 'amount': requestedAmount, + }; + if (!('bizNo' in params)) { + // it doesn't like more than 24 characters + request['bizNo'] = this.uuid22 (); + } + const response = await this.futuresPrivatePostTransferOut (this.extend (request, params)); + // + // { + // code: '200000', + // data: { + // applyId: '605a87217dff1500063d485d', + // bizNo: 'bcd6e5e1291f4905af84dc', + // payAccountType: 'CONTRACT', + // payTag: 'DEFAULT', + // remark: '', + // recAccountType: 'MAIN', + // recTag: 'DEFAULT', + // recRemark: '', + // recSystem: 'KUCOIN', + // status: 'PROCESSING', + // currency: 'XBT', + // amount: '0.00001', + // fee: '0', + // sn: '573688685663948', + // reason: '', + // createdAt: 1616545569000, + // updatedAt: 1616545569000 + // } + // } + // + const data = this.safeValue (response, 'data'); + const timestamp = this.safeInteger (data, 'createdAt'); + const id = this.safeString (data, 'applyId'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const amount = this.safeNumber (data, 'amount'); + const rawStatus = this.safeString (data, 'status'); + let status = undefined; + if (rawStatus === 'PROCESSING') { + status = 'pending'; + } + return { + 'info': response, + 'currency': code, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'amount': amount, + 'fromAccount': fromId, + 'toAccount': toId, + 'id': id, + 'status': status, + }; + } else { + const request = { + 'currency': currency['id'], + 'from': fromId, + 'to': toId, + 'amount': requestedAmount, + }; + if (!('clientOid' in params)) { + request['clientOid'] = this.uuid (); + } + const response = await this.privatePostAccountsInnerTransfer (this.extend (request, params)); + // { code: '200000', data: { orderId: '605a6211e657f00006ad0ad6' } } + const data = this.safeValue (response, 'data'); + const id = this.safeString (data, 'orderId'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'currency': code, + 'amount': requestedAmount, + 'fromAccount': fromId, + 'toAccount': toId, + 'status': undefined, + }; } - return this.parseBalance (result); } async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -1770,11 +1931,11 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'code': code, }; - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'balance'); const direction = this.safeString (item, 'direction'); let before = undefined; if (after !== undefined && amount !== undefined) { @@ -1824,6 +1985,94 @@ module.exports = class kucoin extends Exchange { return this.safeString (types, type, type); } + async fetchPositions (symbols = undefined, params = {}) { + const response = await this.futuresPrivateGetPositions (params); + // + // { + // code: '200000', + // data: [ + // { + // id: '605a9772a229ab0006408258', + // symbol: 'XBTUSDTM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746099, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54371.92, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'USDT', + // isInverse: false + // }, + // { + // id: '605a9772026ac900066550df', + // symbol: 'XBTUSDM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746110, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54354.76, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'XBT', + // isInverse: true + // } + // ] + // } + // + return this.safeValue (response, 'data', response); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { // // the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint @@ -1840,16 +2089,16 @@ module.exports = class kucoin extends Exchange { let endpart = ''; headers = (headers !== undefined) ? headers : {}; if (Object.keys (query).length) { - if (method !== 'GET') { + if ((method === 'GET') || (method === 'DELETE')) { + endpoint += '?' + this.urlencode (query); + } else { body = this.json (query); endpart = body; headers['Content-Type'] = 'application/json'; - } else { - endpoint += '?' + this.urlencode (query); } } const url = this.urls['api'][api] + endpoint; - if (api === 'private') { + if ((api === 'private') || (api === 'futuresPrivate')) { this.checkRequiredCredentials (); const timestamp = this.nonce ().toString (); headers = this.extend ({ @@ -1892,8 +2141,8 @@ module.exports = class kucoin extends Exchange { // { code: '200000', data: { ... }} // const errorCode = this.safeString (response, 'code'); - const message = this.safeString (response, 'msg'); - this.throwExactlyMatchedException (this.exceptions['exact'], message, message); - this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, message); + const message = this.safeString (response, 'msg', ''); + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, this.id + ' ' + message); } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kuna.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kuna.js index e652171d1..0067e406f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kuna.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/kuna.js @@ -2,12 +2,13 @@ // --------------------------------------------------------------------------- -const acx = require ('./acx.js'); -const { ArgumentsRequired } = require ('./base/errors'); +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, InsufficientFunds, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class kuna extends acx { +module.exports = class kuna extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'kuna', @@ -17,14 +18,24 @@ module.exports = class kuna extends acx { 'version': 'v2', 'has': { 'CORS': false, - 'fetchTickers': true, + 'cancelOrder': true, + 'createOrder': true, + 'fetchBalance': true, + 'fetchMarkets': true, + 'fetchMyTrades': true, 'fetchOHLCV': 'emulated', 'fetchOpenOrders': true, - 'fetchMyTrades': true, + 'fetchOrder': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchTime': true, + 'fetchTrades': true, 'withdraw': false, }, 'timeframes': undefined, 'urls': { + 'extension': '.json', 'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4', 'logo': 'https://user-images.githubusercontent.com/51840849/87153927-f0578b80-c2c0-11ea-84b6-74612568e9e1.jpg', 'api': 'https://kuna.io', @@ -32,8 +43,47 @@ module.exports = class kuna extends acx { 'doc': 'https://kuna.io/documents/api', 'fees': 'https://kuna.io/documents/api', }, + 'api': { + 'public': { + 'get': [ + 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. + 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator + 'k', // Get OHLC(k line) of specific market + 'markets', // Get all available markets + 'order_book', // Get the order book of specified market + 'order_book/{market}', + 'tickers', // Get ticker of all markets + 'tickers/{market}', // Get ticker of specific market + 'timestamp', // Get server current time, in seconds since Unix epoch + 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. + 'trades/{market}', + ], + }, + 'private': { + 'get': [ + 'members/me', // Get your profile and accounts info + 'deposits', // Get your deposits history + 'deposit', // Get details of specific deposit + 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. + 'orders', // Get your orders, results is paginated + 'order', // Get information of specified order + 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. + 'withdraws', // Get your cryptocurrency withdraws + 'withdraw', // Get your cryptocurrency withdraw + ], + 'post': [ + 'orders', // Create a Sell/Buy order + 'orders/multi', // Create multiple sell/buy orders + 'orders/clear', // Cancel all my orders + 'order/delete', // Cancel an order + 'withdraw', // Create a withdraw + ], + }, + }, 'fees': { 'trading': { + 'tierBased': false, + 'percentage': true, 'taker': 0.25 / 100, 'maker': 0.25 / 100, }, @@ -56,9 +106,24 @@ module.exports = class kuna extends acx { }, }, }, + 'commonCurrencies': { + 'PLA': 'Plair', + }, + 'exceptions': { + '2002': InsufficientFunds, + '2003': OrderNotFound, + }, }); } + async fetchTime (params = {}) { + const response = await this.publicGetTimestamp (params); + // + // 1594911427 + // + return response * 1000; + } + async fetchMarkets (params = {}) { const quotes = [ 'btc', 'eth', 'eurs', 'rub', 'uah', 'usd', 'usdt', 'gol' ]; const pricePrecisions = { @@ -114,24 +179,100 @@ module.exports = class kuna extends acx { return markets; } - async fetchL3OrderBook (symbol, limit = undefined, params = {}) { - return await this.fetchOrderBook (symbol, limit, params); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); - } + async fetchOrderBook (symbol, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; - const response = await this.privateGetOrders (this.extend (request, params)); - // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder - // with order cache + fetchOpenOrders - // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX - return this.parseOrders (response, market, since, limit); + if (limit !== undefined) { + request['limit'] = limit; // default = 300 + } + const orderbook = await this.publicGetDepth (this.extend (request, params)); + const timestamp = this.safeTimestamp (orderbook, 'timestamp'); + return this.parseOrderBook (orderbook, timestamp); + } + + parseTicker (ticker, market = undefined) { + const timestamp = this.safeTimestamp (ticker, 'at'); + ticker = ticker['ticker']; + let symbol = undefined; + if (market) { + symbol = market['symbol']; + } + const last = this.safeNumber (ticker, 'last'); + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'bidVolume': undefined, + 'ask': this.safeNumber (ticker, 'sell'), + 'askVolume': undefined, + 'vwap': undefined, + 'open': this.safeNumber (ticker, 'open'), + 'close': last, + 'last': last, + 'previousClose': undefined, + 'change': undefined, + 'percentage': undefined, + 'average': undefined, + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const response = await this.publicGetTickers (params); + const ids = Object.keys (response); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + let market = undefined; + let symbol = id; + if (id in this.markets_by_id) { + market = this.markets_by_id[id]; + symbol = market['symbol']; + } else { + let base = id.slice (0, 3); + let quote = id.slice (3, 6); + base = base.toUpperCase (); + quote = quote.toUpperCase (); + base = this.safeCurrencyCode (base); + quote = this.safeCurrencyCode (quote); + symbol = base + '/' + quote; + } + result[symbol] = this.parseTicker (response[id], market); + } + return this.filterByArray (result, 'symbol', symbols); + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTickersMarket (this.extend (request, params)); + return this.parseTicker (response, market); + } + + async fetchL3OrderBook (symbol, limit = undefined, params = {}) { + return await this.fetchOrderBook (symbol, limit, params); + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTrades (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); } parseTrade (trade, market = undefined) { @@ -148,9 +289,14 @@ module.exports = class kuna extends acx { }; side = this.safeString (sideMap, side, side); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_id'); const id = this.safeString (trade, 'id'); return { @@ -170,29 +316,6 @@ module.exports = class kuna extends acx { }; } - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); - } - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.privateGetTradesMy (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const trades = await this.fetchTrades (symbol, since, limit, params); @@ -211,4 +334,198 @@ module.exports = class kuna extends acx { } return result; } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + const response = await this.privateGetMembersMe (params); + const balances = this.safeValue (response, 'accounts'); + const result = { 'info': balances }; + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'market': this.marketId (symbol), + 'side': side, + 'volume': amount.toString (), + 'ord_type': type, + }; + if (type === 'limit') { + request['price'] = price.toString (); + } + const response = await this.privatePostOrders (this.extend (request, params)); + const marketId = this.safeValue (response, 'market'); + const market = this.safeValue (this.markets_by_id, marketId); + return this.parseOrder (response, market); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': id, + }; + const response = await this.privatePostOrderDelete (this.extend (request, params)); + const order = this.parseOrder (response); + const status = order['status']; + if (status === 'closed' || status === 'canceled') { + throw new OrderNotFound (this.id + ' ' + this.json (order)); + } + return order; + } + + parseOrderStatus (status) { + const statuses = { + 'done': 'closed', + 'wait': 'open', + 'cancel': 'canceled', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + const marketId = this.safeString (order, 'market'); + const symbol = this.safeSymbol (marketId, market); + const timestamp = this.parse8601 (this.safeString (order, 'created_at')); + const status = this.parseOrderStatus (this.safeString (order, 'state')); + const type = this.safeString (order, 'type'); + const side = this.safeString (order, 'side'); + const id = this.safeString (order, 'id'); + return this.safeOrder ({ + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': undefined, + 'status': status, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': this.safeNumber (order, 'price'), + 'stopPrice': undefined, + 'amount': this.safeNumber (order, 'volume'), + 'filled': this.safeNumber (order, 'executed_volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'trades': undefined, + 'fee': undefined, + 'info': order, + 'cost': undefined, + 'average': undefined, + }); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': parseInt (id), + }; + const response = await this.privateGetOrder (this.extend (request, params)); + return this.parseOrder (response); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetOrders (this.extend (request, params)); + // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder + // with order cache + fetchOpenOrders + // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX + return this.parseOrders (response, market, since, limit); + } + + async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetTradesMy (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); + } + + nonce () { + return this.milliseconds (); + } + + encodeParams (params) { + if ('orders' in params) { + const orders = params['orders']; + let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); + for (let i = 0; i < orders.length; i++) { + const order = orders[i]; + const keys = Object.keys (order); + for (let k = 0; k < keys.length; k++) { + const key = keys[k]; + const value = order[key]; + query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); + } + } + return query; + } + return this.urlencode (this.keysort (params)); + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let request = '/api/' + this.version + '/' + this.implodeParams (path, params); + if ('extension' in this.urls) { + request += this.urls['extension']; + } + const query = this.omit (params, this.extractParams (path)); + let url = this.urls['api'] + request; + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const nonce = this.nonce ().toString (); + const query = this.encodeParams (this.extend ({ + 'access_key': this.apiKey, + 'tonce': nonce, + }, params)); + const auth = method + '|' + request + '|' + query; + const signed = this.hmac (this.encode (auth), this.encode (this.secret)); + const suffix = query + '&signature=' + signed; + if (method === 'GET') { + url += '?' + suffix; + } else { + body = suffix; + headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; + } + } + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; + } + if (code === 400) { + const error = this.safeValue (response, 'error'); + const errorCode = this.safeString (error, 'code'); + const feedback = this.id + ' ' + this.json (response); + this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); + // fallback to default error handler + } + } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lakebtc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lakebtc.js index 8acd8cc41..991e6ff86 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lakebtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lakebtc.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -112,10 +113,10 @@ module.exports = class lakebtc extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -133,16 +134,16 @@ module.exports = class lakebtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -152,7 +153,7 @@ module.exports = class lakebtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -183,14 +184,11 @@ module.exports = class lakebtc extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/latoken.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/latoken.js index 45cb5951d..ecc53a8c6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/latoken.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/latoken.js @@ -4,7 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, DDoSProtection, BadRequest, AuthenticationError } = require ('./base/errors'); -const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -85,6 +85,7 @@ module.exports = class latoken extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.1 / 100, @@ -169,7 +170,7 @@ module.exports = class latoken extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minQty'), + 'min': this.safeNumber (market, 'minQty'), 'max': undefined, }, 'price': { @@ -219,7 +220,7 @@ module.exports = class latoken extends Exchange { const numericId = this.safeInteger (currency, 'currencyId'); const code = this.safeCurrencyCode (id); const precision = this.safeInteger (currency, 'precission'); - const fee = this.safeFloat (currency, 'fee'); + const fee = this.safeNumber (currency, 'fee'); const active = undefined; result[code] = { 'id': id, @@ -253,27 +254,6 @@ module.exports = class latoken extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const response = await this.privateGetAccountBalances (params); @@ -297,17 +277,15 @@ module.exports = class latoken extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const frozen = this.safeFloat (balance, 'frozen'); - const pending = this.safeFloat (balance, 'pending'); - const used = this.sum (frozen, pending); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': used, - 'total': this.safeFloat (balance, 'amount'), - }; + const frozen = this.safeString (balance, 'frozen'); + const pending = this.safeString (balance, 'pending'); + const account = this.account (); + account['used'] = Precise.stringAdd (frozen, pending); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -352,20 +330,20 @@ module.exports = class latoken extends Exchange { // const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; if (open !== undefined && close !== undefined) { change = close - open; } - const percentage = this.safeFloat (ticker, 'priceChange'); + const percentage = this.safeNumber (ticker, 'priceChange'); const timestamp = this.nonce (); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'low': this.safeFloat (ticker, 'low'), - 'high': this.safeFloat (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -379,7 +357,7 @@ module.exports = class latoken extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -463,22 +441,19 @@ module.exports = class latoken extends Exchange { timestamp *= 1000; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'orderId'); - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -613,29 +588,17 @@ module.exports = class latoken extends Exchange { const symbol = this.safeSymbol (marketId, market); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executedAmount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executedAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderStatus')); - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const timeFilled = this.safeTimestamp (order, 'timeFilled'); let lastTradeTimestamp = undefined; if ((timeFilled !== undefined) && (timeFilled > 0)) { lastTradeTimestamp = timeFilled; } const clientOrderId = this.safeString (order, 'cliOrdId'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -650,14 +613,14 @@ module.exports = class latoken extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'average': undefined, - 'remaining': remaining, + 'remaining': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lbank.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lbank.js index 9b39a0236..e9e4658dc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lbank.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lbank.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -201,8 +202,8 @@ module.exports = class lbank extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const info = ticker; ticker = info['ticker']; - const last = this.safeFloat (ticker, 'latest'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'latest'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; if (percentage !== undefined) { const relativeChange = this.sum (1, percentage / 100); @@ -223,8 +224,8 @@ module.exports = class lbank extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -237,8 +238,8 @@ module.exports = class lbank extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'turnover'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'turnover'), 'info': info, }; } @@ -288,17 +289,15 @@ module.exports = class lbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (trade, 'date_ms'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'tid'); const type = undefined; - const side = this.safeString (trade, 'type'); + let side = this.safeString (trade, 'type'); + side = side.replace ('_market', ''); return { 'id': id, 'info': this.safeValue (trade, 'info', trade), @@ -346,11 +345,11 @@ module.exports = class lbank extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -415,12 +414,12 @@ module.exports = class lbank extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (freeze, currencyId); - account['total'] = this.safeFloat (asset, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (freeze, currencyId); + account['total'] = this.safeString (asset, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -448,35 +447,20 @@ module.exports = class lbank extends Exchange { // "status":2 // } // - let symbol = undefined; - const responseMarket = this.safeValue (this.marketsById, order['symbol']); - if (responseMarket !== undefined) { - symbol = responseMarket['symbol']; - } else if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeInteger (order, 'create_time'); // Limit Order Request Returns: Order Price // Market Order Returns: cny amount of market order - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount', 0.0); - const filled = this.safeFloat (order, 'deal_amount', 0.0); - const av_price = this.safeFloat (order, 'avg_price'); - let cost = undefined; - if (av_price !== undefined) { - cost = filled * av_price; - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount', 0.0); + const filled = this.safeNumber (order, 'deal_amount', 0.0); + const average = this.safeNumber (order, 'avg_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'order_id'); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -490,15 +474,15 @@ module.exports = class lbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': this.safeValue (order, 'info', order), - 'average': undefined, - }; + 'average': average, + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/liquid.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/liquid.js index 732eda853..0365ef102 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/liquid.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/liquid.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported } = require ('./base/errors'); +const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -108,7 +109,7 @@ module.exports = class liquid extends Exchange { 'trading': { 'tierBased': true, 'percentage': true, - 'taker': 0.0015, + 'taker': 0.0030, 'maker': 0.0000, 'tiers': { 'perpetual': { @@ -127,48 +128,52 @@ module.exports = class liquid extends Exchange { [ 300000000, -0.00025 ], ], 'taker': [ - [ 0, 0.000600 ], - [ 25000, 0.000575 ], - [ 50000, 0.000550 ], - [ 100000, 0.000525 ], - [ 1000000, 0.000500 ], - [ 10000000, 0.000475 ], - [ 25000000, 0.000450 ], - [ 50000000, 0.000425 ], - [ 75000000, 0.000400 ], - [ 100000000, 0.000375 ], - [ 200000000, 0.000350 ], - [ 300000000, 0.000325 ], + [ 0, 0.00120 ], + [ 25000, 0.00115 ], + [ 50000, 0.00110 ], + [ 100000, 0.00105 ], + [ 1000000, 0.00100 ], + [ 10000000, 0.00095 ], + [ 25000000, 0.00090 ], + [ 50000000, 0.00085 ], + [ 75000000, 0.00080 ], + [ 100000000, 0.00075 ], + [ 200000000, 0.00070 ], + [ 300000000, 0.00065 ], ], }, 'spot': { 'taker': [ - [ 0, 0.0015 ], - [ 10000, 0.0015 ], - [ 20000, 0.0014 ], - [ 50000, 0.0013 ], - [ 100000, 0.0010 ], - [ 1000000, 0.0008 ], - [ 5000000, 0.0006 ], - [ 10000000, 0.0005 ], - [ 25000000, 0.0005 ], - [ 50000000, 0.00045 ], - [ 100000000, 0.0004 ], - [ 200000000, 0.0003 ], + [ 0, 0.003 ], + [ 10000, 0.0029 ], + [ 20000, 0.0028 ], + [ 50000, 0.0026 ], + [ 100000, 0.0020 ], + [ 1000000, 0.0016 ], + [ 5000000, 0.0012 ], + [ 10000000, 0.0010 ], + [ 25000000, 0.0009 ], + [ 50000000, 0.0008 ], + [ 100000000, 0.0007 ], + [ 200000000, 0.0006 ], + [ 500000000, 0.0004 ], + [ 1000000000, 0.0003 ], ], 'maker': [ [ 0, 0.0000 ], - [ 10000, 0.0015 ], - [ 20000, 0.1400 ], - [ 50000, 0.1300 ], - [ 100000, 0.0800 ], - [ 1000000, 0.0004 ], - [ 5000000, 0.00035 ], - [ 10000000, 0.00025 ], + [ 10000, 0.0020 ], + [ 20000, 0.0019 ], + [ 50000, 0.0018 ], + [ 100000, 0.0016 ], + [ 1000000, 0.0008 ], + [ 5000000, 0.0007 ], + [ 10000000, 0.0005 ], [ 25000000, 0.0000 ], [ 50000000, 0.0000 ], [ 100000000, 0.0000 ], [ 200000000, 0.0000 ], + [ 500000000, 0.0000 ], + [ 1000000000, 0.0000 ], ], }, }, @@ -187,6 +192,7 @@ module.exports = class liquid extends Exchange { 'less_than_order_size': InvalidOrder, 'price_too_high': InvalidOrder, 'price_too_small': InvalidOrder, // {"errors":{"order":["price_too_small"]}} + 'product_disabled': BadSymbol, // {"errors":{"order":["product_disabled"]}} }, 'commonCurrencies': { 'WIN': 'WCOIN', @@ -236,7 +242,7 @@ module.exports = class liquid extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': decimalPrecision, 'limits': { 'amount': { @@ -252,7 +258,7 @@ module.exports = class liquid extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal'), + 'min': this.safeNumber (currency, 'minimum_withdrawal'), 'max': undefined, }, }, @@ -377,19 +383,19 @@ module.exports = class liquid extends Exchange { let maker = this.fees['trading']['maker']; let taker = this.fees['trading']['taker']; if (type === 'swap') { - maker = this.safeFloat (market, 'maker_fee', this.fees['trading']['maker']); - taker = this.safeFloat (market, 'taker_fee', this.fees['trading']['taker']); + maker = this.safeNumber (market, 'maker_fee', this.fees['trading']['maker']); + taker = this.safeNumber (market, 'taker_fee', this.fees['trading']['taker']); } const disabled = this.safeValue (market, 'disabled', false); const active = !disabled; const baseCurrency = this.safeValue (currenciesByCode, base); const precision = { 'amount': 0.00000001, - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; let minAmount = undefined; if (baseCurrency !== undefined) { - minAmount = this.safeFloat (baseCurrency['info'], 'minimum_order_quantity'); + minAmount = this.safeNumber (baseCurrency['info'], 'minimum_order_quantity'); } const limits = { 'amount': { @@ -471,8 +477,8 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } for (let i = 0; i < fiat.length; i++) { @@ -480,11 +486,11 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -503,7 +509,7 @@ module.exports = class liquid extends Exchange { if (ticker['last_traded_price']) { const length = ticker['last_traded_price'].length; if (length > 0) { - last = this.safeFloat (ticker, 'last_traded_price'); + last = this.safeNumber (ticker, 'last_traded_price'); } } } @@ -528,7 +534,7 @@ module.exports = class liquid extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'last_price_24h'); + const open = this.safeNumber (ticker, 'last_price_24h'); if (open !== undefined && last !== undefined) { change = last - open; average = this.sum (last, open) / 2; @@ -540,11 +546,11 @@ module.exports = class liquid extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_market_ask'), - 'low': this.safeFloat (ticker, 'low_market_bid'), - 'bid': this.safeFloat (ticker, 'market_bid'), + 'high': this.safeNumber (ticker, 'high_market_ask'), + 'low': this.safeNumber (ticker, 'low_market_bid'), + 'bid': this.safeNumber (ticker, 'market_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'market_ask'), + 'ask': this.safeNumber (ticker, 'market_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -554,7 +560,7 @@ module.exports = class liquid extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'volume_24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -600,14 +606,11 @@ module.exports = class liquid extends Exchange { if (mySide !== undefined) { takerOrMaker = (takerSide === mySide) ? 'taker' : 'maker'; } - let cost = undefined; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -810,9 +813,9 @@ module.exports = class liquid extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeValue (this.markets_by_id, marketId); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'filled_quantity'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + let filled = this.safeNumber (order, 'filled_quantity'); + const price = this.safeNumber (order, 'price'); let symbol = undefined; let feeCurrency = undefined; if (market !== undefined) { @@ -822,7 +825,7 @@ module.exports = class liquid extends Exchange { const type = this.safeString (order, 'order_type'); let tradeCost = 0; let tradeFilled = 0; - let average = this.safeFloat (order, 'average_price'); + let average = this.safeNumber (order, 'average_price'); const trades = this.parseTrades (this.safeValue (order, 'executions', []), market, undefined, undefined, { 'order': orderId, 'type': type, @@ -879,7 +882,7 @@ module.exports = class liquid extends Exchange { 'trades': trades, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'order_fee'), + 'cost': this.safeNumber (order, 'order_fee'), }, 'info': order, }; @@ -1034,7 +1037,7 @@ module.exports = class liquid extends Exchange { const updated = this.safeTimestamp (transaction, 'updated_at'); const type = 'withdrawal'; const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/luno.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/luno.js index 2bbec0ec1..ad5568218 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/luno.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/luno.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -79,6 +80,10 @@ module.exports = class luno extends Exchange { 'quotes/{id}', 'withdrawals', 'withdrawals/{id}', + 'transfers', + // GET /api/exchange/2/listorders + // GET /api/exchange/2/orders/{id} + // GET /api/exchange/3/order ], 'post': [ 'accounts', @@ -153,12 +158,12 @@ module.exports = class luno extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), - 'max': this.safeFloat (market, 'max_volume'), + 'min': this.safeNumber (market, 'min_volume'), + 'max': this.safeNumber (market, 'max_volume'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -209,20 +214,22 @@ module.exports = class luno extends Exchange { const wallet = wallets[i]; const currencyId = this.safeString (wallet, 'asset'); const code = this.safeCurrencyCode (currencyId); - const reserved = this.safeFloat (wallet, 'reserved'); - const unconfirmed = this.safeFloat (wallet, 'unconfirmed'); - const balance = this.safeFloat (wallet, 'balance'); + const reserved = this.safeString (wallet, 'reserved'); + const unconfirmed = this.safeString (wallet, 'unconfirmed'); + const balance = this.safeString (wallet, 'balance'); + const reservedUnconfirmed = Precise.stringAdd (reserved, unconfirmed); + const balanceUnconfirmed = Precise.stringAdd (balance, unconfirmed); if (code in result) { - result[code]['used'] = this.sum (result[code]['used'], reserved, unconfirmed); - result[code]['total'] = this.sum (result[code]['total'], balance, unconfirmed); + result[code]['used'] = Precise.stringAdd (result[code]['used'], reservedUnconfirmed); + result[code]['total'] = Precise.stringAdd (result[code]['total'], balanceUnconfirmed); } else { const account = this.account (); - account['used'] = this.sum (reserved, unconfirmed); - account['total'] = this.sum (balance, unconfirmed); + account['used'] = reservedUnconfirmed; + account['total'] = balanceUnconfirmed; result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -273,18 +280,12 @@ module.exports = class luno extends Exchange { const side = (order['type'] === 'ASK') ? 'sell' : 'buy'; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'limit_volume'); - const quoteFee = this.safeFloat (order, 'fee_counter'); - const baseFee = this.safeFloat (order, 'fee_base'); - const filled = this.safeFloat (order, 'base'); - const cost = this.safeFloat (order, 'counter'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'limit_volume'); + const quoteFee = this.safeNumber (order, 'fee_counter'); + const baseFee = this.safeNumber (order, 'fee_base'); + const filled = this.safeNumber (order, 'base'); + const cost = this.safeNumber (order, 'counter'); const fee = { 'currency': undefined }; if (quoteFee) { fee['cost'] = quoteFee; @@ -298,7 +299,7 @@ module.exports = class luno extends Exchange { } } const id = this.safeString (order, 'order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -315,12 +316,12 @@ module.exports = class luno extends Exchange { 'amount': amount, 'filled': filled, 'cost': cost, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -366,16 +367,16 @@ module.exports = class luno extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -385,7 +386,7 @@ module.exports = class luno extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'rolling_24_hour_volume'), + 'baseVolume': this.safeNumber (ticker, 'rolling_24_hour_volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -436,8 +437,8 @@ module.exports = class luno extends Exchange { } else { side = trade['is_buy'] ? 'buy' : 'sell'; } - const feeBase = this.safeFloat (trade, 'fee_base'); - const feeCounter = this.safeFloat (trade, 'fee_counter'); + const feeBase = this.safeNumber (trade, 'fee_base'); + const feeCounter = this.safeNumber (trade, 'fee_counter'); let feeCurrency = undefined; let feeCost = undefined; if (feeBase !== undefined) { @@ -462,10 +463,10 @@ module.exports = class luno extends Exchange { 'type': undefined, 'side': side, 'takerOrMaker': takerOrMaker, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), // Does not include potential fee costs - 'cost': this.safeFloat (trade, 'counter'), + 'cost': this.safeNumber (trade, 'counter'), 'fee': { 'cost': feeCost, 'currency': feeCurrency, @@ -512,8 +513,8 @@ module.exports = class luno extends Exchange { const response = await this.privateGetFeeInfo (params); return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } @@ -647,9 +648,9 @@ module.exports = class luno extends Exchange { const timestamp = this.safeValue (entry, 'timestamp'); const currencyId = this.safeString (entry, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - const available_delta = this.safeFloat (entry, 'available_delta'); - const balance_delta = this.safeFloat (entry, 'balance_delta'); - const after = this.safeFloat (entry, 'balance'); + const available_delta = this.safeNumber (entry, 'available_delta'); + const balance_delta = this.safeNumber (entry, 'balance_delta'); + const after = this.safeNumber (entry, 'balance'); const comment = this.safeString (entry, 'description'); let before = after; let amount = 0.0; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lykke.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lykke.js index edc0fe73a..707034d20 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lykke.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/lykke.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -184,18 +185,16 @@ module.exports = class lykke extends Exchange { const id = this.safeString2 (trade, 'id', 'Id'); const orderId = this.safeString (trade, 'OrderId'); const timestamp = this.parse8601 (this.safeString2 (trade, 'dateTime', 'DateTime')); - const price = this.safeFloat2 (trade, 'price', 'Price'); - let amount = this.safeFloat2 (trade, 'volume', 'Amount'); + const priceString = this.safeString2 (trade, 'price', 'Price'); + let amountString = this.safeString2 (trade, 'volume', 'Amount'); let side = this.safeStringLower (trade, 'action'); if (side === undefined) { - if (amount < 0) { - side = 'sell'; - } else { - side = 'buy'; - } + side = (amountString[0] === '-') ? 'sell' : 'buy'; } - amount = Math.abs (amount); - const cost = price * amount; + amountString = (amountString[0] === '-') ? amountString.slice (1) : amountString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = { 'cost': 0, // There are no fees for trading. https://www.lykke.com/wallet-fees-and-limits/ 'currency': market['quote'], @@ -256,11 +255,11 @@ module.exports = class lykke extends Exchange { const currencyId = this.safeString (balance, 'AssetId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Balance'); - account['used'] = this.safeFloat (balance, 'Reserved'); + account['total'] = this.safeString (balance, 'Balance'); + account['used'] = this.safeString (balance, 'Reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -307,7 +306,7 @@ module.exports = class lykke extends Exchange { // } // const id = this.safeString (result, 'Id'); - price = this.safeFloat (result, 'Price'); + price = this.safeNumber (result, 'Price'); return { 'id': id, 'info': result, @@ -398,16 +397,16 @@ module.exports = class lykke extends Exchange { if (market) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'lastPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -418,7 +417,7 @@ module.exports = class lykke extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume24H'), + 'quoteVolume': this.safeNumber (ticker, 'volume24H'), 'info': ticker, }; } @@ -476,20 +475,18 @@ module.exports = class lykke extends Exchange { } else if (('CreatedAt' in order) && (order['CreatedAt'])) { timestamp = this.parse8601 (order['CreatedAt']); } - const price = this.safeFloat (order, 'Price'); + const price = this.safeNumber (order, 'Price'); let side = undefined; - let amount = this.safeFloat (order, 'Volume'); + let amount = this.safeNumber (order, 'Volume'); if (amount < 0) { side = 'sell'; amount = Math.abs (amount); } else { side = 'buy'; } - const remaining = Math.abs (this.safeFloat (order, 'RemainingVolume')); - const filled = amount - remaining; - const cost = filled * price; + const remaining = Math.abs (this.safeNumber (order, 'RemainingVolume')); const id = this.safeString (order, 'Id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -503,15 +500,15 @@ module.exports = class lykke extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -572,8 +569,8 @@ module.exports = class lykke extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - let amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + let amount = this.safeNumber (bidask, amountKey); if (amount < 0) { amount = -amount; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mercado.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mercado.js index a2fd9593e..2746e14b8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mercado.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mercado.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -160,7 +161,7 @@ module.exports = class mercado extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, baseId), + 'min': this.safeNumber (amountLimits, baseId), 'max': undefined, }, 'price': { @@ -196,16 +197,16 @@ module.exports = class mercado extends Exchange { const response = await this.publicGetCoinTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'ticker', {}); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -215,7 +216,7 @@ module.exports = class mercado extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -230,15 +231,12 @@ module.exports = class mercado extends Exchange { const id = this.safeString2 (trade, 'tid', 'operation_id'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee_rate'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee_rate'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -295,12 +293,12 @@ module.exports = class mercado extends Exchange { if (currencyId in balances) { const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -407,32 +405,31 @@ module.exports = class mercado extends Exchange { // } // const id = this.safeString (order, 'order_id'); + const order_type = this.safeString (order, 'order_type'); let side = undefined; if ('order_type' in order) { - side = (order['order_type'] === 1) ? 'buy' : 'sell'; + side = (order_type === '1') ? 'buy' : 'sell'; } const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'coin_pair'); market = this.safeMarket (marketId, market); const timestamp = this.safeTimestamp (order, 'created_timestamp'); const fee = { - 'cost': this.safeFloat (order, 'fee'), + 'cost': this.safeNumber (order, 'fee'), 'currency': market['quote'], }; - const price = this.safeFloat (order, 'limit_price'); - // price = this.safeFloat (order, 'executed_price_avg', price); - const average = this.safeFloat (order, 'executed_price_avg'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'executed_quantity'); - const remaining = amount - filled; - const cost = filled * average; + const price = this.safeNumber (order, 'limit_price'); + // price = this.safeNumber (order, 'executed_price_avg', price); + const average = this.safeNumber (order, 'executed_price_avg'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const lastTradeTimestamp = this.safeTimestamp (order, 'updated_timestamp'); const rawTrades = this.safeValue (order, 'operations', []); const trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'side': side, 'order': id, }); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -446,15 +443,15 @@ module.exports = class mercado extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -512,11 +509,11 @@ module.exports = class mercado extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mixcoins.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mixcoins.js index 85138f138..11bbf93b6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mixcoins.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/mixcoins.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -72,11 +73,11 @@ module.exports = class mixcoins extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.safeFloat (balance, 'lock'); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = this.safeString (balance, 'lock'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -96,16 +97,16 @@ module.exports = class mixcoins extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'result'); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -115,7 +116,7 @@ module.exports = class mixcoins extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -128,14 +129,11 @@ module.exports = class mixcoins extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ndax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ndax.js index 0367c2695..37e8b2760 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ndax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ndax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -244,7 +245,7 @@ module.exports = class ndax extends Exchange { const name = this.safeString (currency, 'ProductFullName'); const type = this.safeString (currency, 'ProductType'); const code = this.safeCurrencyCode (this.safeString (currency, 'Product')); - const precision = this.safeFloat (currency, 'TickSize'); + const precision = this.safeNumber (currency, 'TickSize'); const isDisabled = this.safeValue (currency, 'IsDisabled'); const active = !isDisabled; result[code] = { @@ -325,8 +326,8 @@ module.exports = class ndax extends Exchange { const quote = this.safeCurrencyCode (this.safeString (market, 'Product2Symbol')); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'QuantityIncrement'), - 'price': this.safeFloat (market, 'PriceIncrement'), + 'amount': this.safeNumber (market, 'QuantityIncrement'), + 'price': this.safeNumber (market, 'PriceIncrement'), }; const sessionStatus = this.safeString (market, 'SessionStatus'); const isDisable = this.safeValue (market, 'IsDisable'); @@ -344,11 +345,11 @@ module.exports = class ndax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinimumQuantity'), + 'min': this.safeNumber (market, 'MinimumQuantity'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'MinimumPrice'), + 'min': this.safeNumber (market, 'MinimumPrice'), 'max': undefined, }, 'cost': { @@ -469,27 +470,27 @@ module.exports = class ndax extends Exchange { const timestamp = this.safeInteger (ticker, 'TimeStamp'); const marketId = this.safeString (ticker, 'InstrumentId'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'LastTradedPx'); - const percentage = this.safeFloat (ticker, 'Rolling24HrPxChangePercent'); - const change = this.safeFloat (ticker, 'Rolling24HrPxChange'); - const open = this.safeFloat (ticker, 'SessionOpen'); + const last = this.safeNumber (ticker, 'LastTradedPx'); + const percentage = this.safeNumber (ticker, 'Rolling24HrPxChangePercent'); + const change = this.safeNumber (ticker, 'Rolling24HrPxChange'); + const open = this.safeNumber (ticker, 'SessionOpen'); let average = undefined; if ((last !== undefined) && (change !== undefined)) { average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'Rolling24HrVolume'); - const quoteVolume = this.safeFloat (ticker, 'Rolling24HrNotional'); + const baseVolume = this.safeNumber (ticker, 'Rolling24HrVolume'); + const quoteVolume = this.safeNumber (ticker, 'Rolling24HrNotional'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'SessionHigh'), - 'low': this.safeFloat (ticker, 'SessionLow'), - 'bid': this.safeFloat (ticker, 'BestBid'), - 'bidVolume': undefined, // this.safeFloat (ticker, 'BidQty'), always shows 0 - 'ask': this.safeFloat (ticker, 'BestOffer'), - 'askVolume': undefined, // this.safeFloat (ticker, 'AskQty'), always shows 0 + 'high': this.safeNumber (ticker, 'SessionHigh'), + 'low': this.safeNumber (ticker, 'SessionLow'), + 'bid': this.safeNumber (ticker, 'BestBid'), + 'bidVolume': undefined, // this.safeNumber (ticker, 'BidQty'), always shows 0 + 'ask': this.safeNumber (ticker, 'BestOffer'), + 'askVolume': undefined, // this.safeNumber (ticker, 'AskQty'), always shows 0 'vwap': vwap, 'open': open, 'close': last, @@ -562,11 +563,11 @@ module.exports = class ndax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -714,8 +715,8 @@ module.exports = class ndax extends Exchange { // "OMSId":1 // } // - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let cost = undefined; let timestamp = undefined; let id = undefined; @@ -726,11 +727,8 @@ module.exports = class ndax extends Exchange { let fee = undefined; let type = undefined; if (Array.isArray (trade)) { - price = this.safeFloat (trade, 3); - amount = this.safeFloat (trade, 2); - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + priceString = this.safeString (trade, 3); + amountString = this.safeString (trade, 2); timestamp = this.safeInteger (trade, 6); id = this.safeString (trade, 0); marketId = this.safeInteger (trade, 1); @@ -742,13 +740,13 @@ module.exports = class ndax extends Exchange { id = this.safeString (trade, 'TradeId'); orderId = this.safeString2 (trade, 'OrderId', 'OrigOrderId'); marketId = this.safeString2 (trade, 'InstrumentId', 'Instrument'); - price = this.safeFloat (trade, 'Price'); - amount = this.safeFloat (trade, 'Quantity'); - cost = this.safeFloat2 (trade, 'Value', 'GrossValueExecuted'); + priceString = this.safeString (trade, 'Price'); + amountString = this.safeString (trade, 'Quantity'); + cost = this.safeNumber2 (trade, 'Value', 'GrossValueExecuted'); takerOrMaker = this.safeStringLower (trade, 'MakerTaker'); side = this.safeStringLower (trade, 'Side'); type = this.safeStringLower (trade, 'OrderType'); - const feeCost = this.safeFloat (trade, 'Fee'); + const feeCost = this.safeNumber (trade, 'Fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'FeeProductId'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -758,6 +756,11 @@ module.exports = class ndax extends Exchange { }; } } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const symbol = this.safeSymbol (marketId, market); return { 'info': trade, @@ -872,11 +875,11 @@ module.exports = class ndax extends Exchange { const currencyId = this.safeString (balance, 'ProductId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Amount'); - account['used'] = this.safeFloat (balance, 'Hold'); + account['total'] = this.safeString (balance, 'Amount'); + account['used'] = this.safeString (balance, 'Hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseLedgerEntryType (type) { @@ -922,8 +925,8 @@ module.exports = class ndax extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'ReferenceType')); const currencyId = this.safeString (item, 'ProductId'); const code = this.safeCurrencyCode (currencyId, currency); - const credit = this.safeFloat (item, 'CR'); - const debit = this.safeFloat (item, 'DR'); + const credit = this.safeNumber (item, 'CR'); + const debit = this.safeNumber (item, 'DR'); let amount = undefined; let direction = undefined; if (credit > 0) { @@ -935,7 +938,7 @@ module.exports = class ndax extends Exchange { } const timestamp = this.safeInteger (item, 'TimeStamp'); let before = undefined; - const after = this.safeFloat (item, 'Balance'); + const after = this.safeNumber (item, 'Balance'); if (direction === 'out') { before = this.sum (after, amount); } else if (direction === 'in') { @@ -1083,36 +1086,26 @@ module.exports = class ndax extends Exchange { // const id = this.safeString2 (order, 'ReplacementOrderId', 'OrderId'); const timestamp = this.safeInteger (order, 'ReceiveTime'); - let lastTradeTimestamp = undefined; + const lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); const marketId = this.safeString (order, 'Instrument'); const symbol = this.safeSymbol (marketId, market); const side = this.safeStringLower (order, 'Side'); const type = this.safeStringLower (order, 'OrderType'); const clientOrderId = this.safeString2 (order, 'ReplacementClOrdId', 'ClientOrderId'); - let price = this.safeFloat (order, 'Price', 0.0); + let price = this.safeNumber (order, 'Price', 0.0); price = (price > 0.0) ? price : undefined; - const amount = this.safeFloat (order, 'OrigQuantity'); - const filled = this.safeFloat (order, 'QuantityExecuted'); - const cost = this.safeFloat (order, 'GrossValueExecuted'); - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (filled > 0) { - lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); - average = this.safeFloat (order, 'AvgPrice', 0.0); - average = (average > 0) ? average : undefined; - } - } - let stopPrice = this.safeFloat (order, 'StopPrice', 0.0); + const amount = this.safeNumber (order, 'OrigQuantity'); + const filled = this.safeNumber (order, 'QuantityExecuted'); + const cost = this.safeNumber (order, 'GrossValueExecuted'); + let average = this.safeNumber (order, 'AvgPrice', 0.0); + average = (average > 0) ? average : undefined; + let stopPrice = this.safeNumber (order, 'StopPrice', 0.0); stopPrice = (stopPrice > 0.0) ? stopPrice : undefined; const timeInForce = undefined; const status = this.parseOrderStatus (this.safeString (order, 'OrderState')); const fee = undefined; const trades = undefined; - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -1131,10 +1124,10 @@ module.exports = class ndax extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1932,8 +1925,8 @@ module.exports = class ndax extends Exchange { } const addressTo = address; const status = this.parseTransactionStatusByType (this.safeString (transaction, 'TicketStatus'), type); - const amount = this.safeFloat (transaction, 'Amount'); - const feeCost = this.safeFloat (transaction, 'FeeAmount'); + const amount = this.safeNumber (transaction, 'Amount'); + const feeCost = this.safeNumber (transaction, 'FeeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/novadax.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/novadax.js index dfc6569d2..76f763414 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/novadax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/novadax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, BadRequest, CancelPending, OrderNotFound, InsufficientFunds, RateLimitExceeded, InvalidOrder, AccountSuspended, BadSymbol, OnMaintenance } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -197,7 +198,7 @@ module.exports = class novadax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -205,7 +206,7 @@ module.exports = class novadax extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderValue'), + 'min': this.safeNumber (market, 'minOrderValue'), 'max': undefined, }, }; @@ -247,8 +248,8 @@ module.exports = class novadax extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const open = this.safeFloat (ticker, 'open24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'open24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let percentage = undefined; let change = undefined; let average = undefined; @@ -257,18 +258,18 @@ module.exports = class novadax extends Exchange { percentage = change / open * 100; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'baseVolume24h'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume24h'); + const baseVolume = this.safeNumber (ticker, 'baseVolume24h'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -424,11 +425,13 @@ module.exports = class novadax extends Exchange { const orderId = this.safeString (trade, 'orderId'); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeStringLower (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - cost = amount * price; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'volume'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); @@ -440,7 +443,7 @@ module.exports = class novadax extends Exchange { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { - 'cost': this.safeFloat (parts, 0), + 'cost': this.safeNumber (parts, 0), 'currency': feeCurrencyCode, }; } @@ -548,11 +551,11 @@ module.exports = class novadax extends Exchange { const volumeField = this.safeString (options, 'volume', 'amount'); // or vol return [ this.safeTimestamp (ohlcv, 'score'), - this.safeFloat (ohlcv, 'openPrice'), - this.safeFloat (ohlcv, 'highPrice'), - this.safeFloat (ohlcv, 'lowPrice'), - this.safeFloat (ohlcv, 'closePrice'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'openPrice'), + this.safeNumber (ohlcv, 'highPrice'), + this.safeNumber (ohlcv, 'lowPrice'), + this.safeNumber (ohlcv, 'closePrice'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -580,12 +583,12 @@ module.exports = class novadax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'available'); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); + account['total'] = this.safeString (balance, 'available'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -608,7 +611,7 @@ module.exports = class novadax extends Exchange { if (uppercaseSide === 'SELL') { request['amount'] = this.amountToPrecision (symbol, amount); } else if (uppercaseSide === 'BUY') { - let value = this.safeFloat (params, 'value'); + let value = this.safeNumber (params, 'value'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -838,21 +841,17 @@ module.exports = class novadax extends Exchange { // } // const id = this.safeString (order, 'id'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'filledValue'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'filledValue'); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeInteger (order, 'timestamp'); - const average = this.safeFloat (order, 'averagePrice'); - const filled = this.safeFloat (order, 'filledAmount'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } + const average = this.safeNumber (order, 'averagePrice'); + const filled = this.safeNumber (order, 'filledAmount'); let fee = undefined; - const feeCost = this.safeFloat (order, 'filledFee'); + const feeCost = this.safeNumber (order, 'filledFee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -861,7 +860,7 @@ module.exports = class novadax extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -879,11 +878,11 @@ module.exports = class novadax extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async withdraw (code, amount, address, tag = undefined, params = {}) { @@ -1046,7 +1045,7 @@ module.exports = class novadax extends Exchange { } else if (type === 'COIN_OUT') { type = 'withdraw'; } - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'addressTag'); const txid = this.safeString (transaction, 'txHash'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/oceanex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/oceanex.js index 28cb8e857..6073f75d5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/oceanex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/oceanex.js @@ -147,10 +147,10 @@ module.exports = class oceanex extends Exchange { 'active': true, 'info': market, 'precision': { - 'amount': this.safeValue (market, 'amount_precision'), - 'price': this.safeValue (market, 'price_precision'), - 'base': this.safeValue (market, 'ask_precision'), - 'quote': this.safeValue (market, 'bid_precision'), + 'amount': this.safeInteger (market, 'amount_precision'), + 'price': this.safeInteger (market, 'price_precision'), + 'base': this.safeInteger (market, 'ask_precision'), + 'quote': this.safeInteger (market, 'bid_precision'), }, 'limits': { 'amount': { @@ -162,7 +162,7 @@ module.exports = class oceanex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeValue (market, 'minimum_trading_amount'), + 'min': this.safeNumber (market, 'minimum_trading_amount'), 'max': undefined, }, }, @@ -256,21 +256,21 @@ module.exports = class oceanex extends Exchange { 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (ticker, 'last'), - 'last': this.safeFloat (ticker, 'last'), + 'close': this.safeNumber (ticker, 'last'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -395,8 +395,8 @@ module.exports = class oceanex extends Exchange { 'type': 'limit', 'takerOrMaker': undefined, 'side': side, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), 'cost': undefined, 'fee': undefined, }; @@ -423,8 +423,8 @@ module.exports = class oceanex extends Exchange { result[symbol] = { 'info': group, 'symbol': symbol, - 'maker': this.safeFloat (maker, 'value'), - 'taker': this.safeFloat (taker, 'value'), + 'maker': this.safeNumber (maker, 'value'), + 'taker': this.safeNumber (taker, 'value'), }; } return result; @@ -446,11 +446,11 @@ module.exports = class oceanex extends Exchange { const currencyId = this.safeValue (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -558,12 +558,12 @@ module.exports = class oceanex extends Exchange { // const status = this.parseOrderStatus (this.safeValue (order, 'state')); const marketId = this.safeString2 (order, 'market', 'market_id'); - const symbol = this.safeSymbol (marketId); + const symbol = this.safeSymbol (marketId, market); let timestamp = this.safeTimestamp (order, 'created_on'); if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'created_at')); } - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, @@ -575,17 +575,17 @@ module.exports = class oceanex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeValue (order, 'side'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_price'), - 'amount': this.safeFloat (order, 'volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'filled': this.safeFloat (order, 'executed_volume'), + 'average': this.safeNumber (order, 'avg_price'), + 'amount': this.safeNumber (order, 'volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'filled': this.safeNumber (order, 'executed_volume'), 'status': status, 'cost': undefined, 'trades': undefined, 'fee': undefined, - }; + }); } parseOrderStatus (status) { @@ -678,7 +678,7 @@ module.exports = class oceanex extends Exchange { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['codes'], errorCode, feedback); this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - throw new ExchangeError (response); + throw new ExchangeError (feedback); } } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/okex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/okex.js index b9b09c4e0..02d686c17 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/okex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/okex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -798,7 +799,7 @@ module.exports = class okex extends Exchange { let option = false; let baseId = this.safeString (market, 'base_currency'); let quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { if ('option_type' in market) { marketType = 'option'; @@ -824,12 +825,12 @@ module.exports = class okex extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = spot ? (base + '/' + quote) : id; - const lotSize = this.safeFloat2 (market, 'lot_size', 'trade_increment'); + const lotSize = this.safeNumber2 (market, 'lot_size', 'trade_increment'); const precision = { - 'amount': this.safeFloat (market, 'size_increment', lotSize), - 'price': this.safeFloat (market, 'tick_size'), + 'amount': this.safeNumber (market, 'size_increment', lotSize), + 'price': this.safeNumber (market, 'tick_size'), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const active = true; const fees = this.safeValue2 (this.fees, marketType, 'trading', {}); return this.extend (fees, { @@ -1004,7 +1005,7 @@ module.exports = class okex extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal'), + 'min': this.safeNumber (currency, 'min_withdrawal'), 'max': undefined, }, }, @@ -1079,18 +1080,18 @@ module.exports = class okex extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open_24h'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open_24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_24h'), - 'low': this.safeFloat (ticker, 'low_24h'), - 'bid': this.safeFloat (ticker, 'best_bid'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (ticker, 'best_ask'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber (ticker, 'high_24h'), + 'low': this.safeNumber (ticker, 'low_24h'), + 'bid': this.safeNumber (ticker, 'best_bid'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (ticker, 'best_ask'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': undefined, 'open': open, 'close': last, @@ -1099,8 +1100,8 @@ module.exports = class okex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'base_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'quote_volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'base_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'quote_volume_24h'), 'info': ticker, }; } @@ -1237,9 +1238,12 @@ module.exports = class okex extends Exchange { quote = market['quote']; } const timestamp = this.parse8601 (this.safeString2 (trade, 'timestamp', 'created_at')); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'size', 'qty'); - amount = this.safeFloat (trade, 'order_qty', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'size', 'qty'); + amountString = this.safeString (trade, 'order_qty', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -1247,13 +1251,7 @@ module.exports = class okex extends Exchange { takerOrMaker = 'taker'; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -1362,22 +1360,22 @@ module.exports = class okex extends Exchange { } return [ timestamp, // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets ]; } else { return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, 'volume'), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, 'volume'), // Base Volume ]; } } @@ -1523,9 +1521,9 @@ module.exports = class okex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeNumber (balance, 'balance'); + account['used'] = this.safeNumber (balance, 'hold'); + account['free'] = this.safeNumber (balance, 'available'); result[code] = account; } return this.parseBalance (result); @@ -1595,9 +1593,9 @@ module.exports = class okex extends Exchange { const currencyId = parts[1]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (marketBalance, 'balance'); - account['used'] = this.safeFloat (marketBalance, 'hold'); - account['free'] = this.safeFloat (marketBalance, 'available'); + account['total'] = this.safeNumber (marketBalance, 'balance'); + account['used'] = this.safeNumber (marketBalance, 'hold'); + account['free'] = this.safeNumber (marketBalance, 'available'); accounts[code] = account; } else { throw new NotSupported (this.id + ' margin balance response format has changed!'); @@ -1650,29 +1648,29 @@ module.exports = class okex extends Exchange { const code = this.safeCurrencyCode (id); const balance = this.safeValue (info, id, {}); const account = this.account (); - const totalAvailBalance = this.safeFloat (balance, 'total_avail_balance'); + const totalAvailBalance = this.safeNumber (balance, 'total_avail_balance'); if (this.safeString (balance, 'margin_mode') === 'fixed') { const contracts = this.safeValue (balance, 'contracts', []); let free = totalAvailBalance; for (let i = 0; i < contracts.length; i++) { const contract = contracts[i]; - const fixedBalance = this.safeFloat (contract, 'fixed_balance'); - const realizedPnl = this.safeFloat (contract, 'realized_pnl'); - const marginFrozen = this.safeFloat (contract, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (contract, 'margin_for_unfilled'); + const fixedBalance = this.safeNumber (contract, 'fixed_balance'); + const realizedPnl = this.safeNumber (contract, 'realized_pnl'); + const marginFrozen = this.safeNumber (contract, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (contract, 'margin_for_unfilled'); const margin = this.sum (fixedBalance, realizedPnl) - marginFrozen - marginForUnfilled; free = this.sum (free, margin); } account['free'] = free; } else { - const realizedPnl = this.safeFloat (balance, 'realized_pnl'); - const unrealizedPnl = this.safeFloat (balance, 'unrealized_pnl'); - const marginFrozen = this.safeFloat (balance, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (balance, 'margin_for_unfilled'); + const realizedPnl = this.safeNumber (balance, 'realized_pnl'); + const unrealizedPnl = this.safeNumber (balance, 'unrealized_pnl'); + const marginFrozen = this.safeNumber (balance, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (balance, 'margin_for_unfilled'); account['free'] = this.sum (totalAvailBalance, realizedPnl, unrealizedPnl) - marginFrozen - marginForUnfilled; } // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); + account['total'] = this.safeNumber (balance, 'equity'); result[code] = account; } return this.parseBalance (result); @@ -1710,8 +1708,8 @@ module.exports = class okex extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeNumber (balance, 'equity'); + account['free'] = this.safeNumber (balance, 'total_avail_balance'); result[symbol] = account; } return this.parseBalance (result); @@ -1915,7 +1913,7 @@ module.exports = class okex extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2125,8 +2123,8 @@ module.exports = class okex extends Exchange { symbol = market['symbol']; } } - let amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat2 (order, 'filled_size', 'filled_qty'); + let amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber2 (order, 'filled_size', 'filled_qty'); let remaining = undefined; if (amount !== undefined) { if (filled !== undefined) { @@ -2137,9 +2135,9 @@ module.exports = class okex extends Exchange { if (type === 'market') { remaining = 0; } - let cost = this.safeFloat2 (order, 'filled_notional', 'funds'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); + let cost = this.safeNumber2 (order, 'filled_notional', 'funds'); + const price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'price_avg'); if (cost === undefined) { if (filled !== undefined && average !== undefined) { cost = average * filled; @@ -2150,7 +2148,7 @@ module.exports = class okex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'state')); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -2163,7 +2161,7 @@ module.exports = class okex extends Exchange { if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) { clientOrderId = undefined; // fix empty clientOrderId string } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); return { 'info': order, 'id': id, @@ -2407,16 +2405,6 @@ module.exports = class okex extends Exchange { return await this.fetchOrdersByState ('7', symbol, since, limit, params); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -2444,7 +2432,8 @@ module.exports = class okex extends Exchange { async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); - const currency = this.currency (code); + const parts = code.split ('-'); + const currency = this.currency (parts[0]); const request = { 'currency': currency['id'], }; @@ -2457,8 +2446,8 @@ module.exports = class okex extends Exchange { // } // ] // - const addresses = this.parseDepositAddresses (response); - const address = this.safeValue (addresses, code); + const addressesByCode = this.parseDepositAddresses (response); + const address = this.safeValue (addressesByCode, code); if (address === undefined) { throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first'); } @@ -2633,7 +2622,7 @@ module.exports = class okex extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const txid = this.safeString (transaction, 'txid'); const timestamp = this.parse8601 (this.safeString (transaction, 'timestamp')); @@ -2696,19 +2685,19 @@ module.exports = class okex extends Exchange { let feeCurrencyId = undefined; if (receivedCurrencyId === quoteId) { side = this.safeString (otherTrade, 'side'); - amount = this.safeFloat (otherTrade, 'size'); - cost = this.safeFloat (userTrade, 'size'); + amount = this.safeNumber (otherTrade, 'size'); + cost = this.safeNumber (userTrade, 'size'); feeCurrencyId = this.safeString (otherTrade, 'currency'); } else { side = this.safeString (userTrade, 'side'); - amount = this.safeFloat (userTrade, 'size'); - cost = this.safeFloat (otherTrade, 'size'); + amount = this.safeNumber (userTrade, 'size'); + cost = this.safeNumber (otherTrade, 'size'); feeCurrencyId = this.safeString (userTrade, 'currency'); } const id = this.safeString (userTrade, 'trade_id'); - const price = this.safeFloat (userTrade, 'price'); - const feeCostFirst = this.safeFloat (otherTrade, 'fee'); - const feeCostSecond = this.safeFloat (userTrade, 'fee'); + const price = this.safeNumber (userTrade, 'price'); + const feeCostFirst = this.safeNumber (otherTrade, 'fee'); + const feeCostSecond = this.safeNumber (userTrade, 'fee'); const feeCurrencyCodeFirst = this.safeCurrencyCode (this.safeString (otherTrade, 'currency')); const feeCurrencyCodeSecond = this.safeCurrencyCode (this.safeString (userTrade, 'currency')); let fee = undefined; @@ -3140,7 +3129,7 @@ module.exports = class okex extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); let method = undefined; const defaultType = this.safeString2 (this.options, 'fetchPositions', 'defaultType'); @@ -3522,14 +3511,14 @@ module.exports = class okex extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'timestamp')); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; const marketId = this.safeString (item, 'instrument_id'); let symbol = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/paymium.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/paymium.js index 1af0c5355..2d0d8418c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/paymium.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/paymium.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -96,12 +97,12 @@ module.exports = class paymium extends Exchange { if (free in response) { const account = this.account (); const used = 'locked_' + currencyId; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -120,30 +121,30 @@ module.exports = class paymium extends Exchange { }; const ticker = await this.publicGetDataCurrencyTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'at'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'price'); + const last = this.safeNumber (ticker, 'price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'variation'), + 'percentage': this.safeNumber (ticker, 'variation'), 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, @@ -159,15 +160,12 @@ module.exports = class paymium extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); + const priceString = this.safeString (trade, 'price'); const amountField = 'traded_' + market['base'].toLowerCase (); - const amount = this.safeFloat (trade, amountField); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const amountString = this.safeString (trade, amountField); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/phemex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/phemex.js index b1c294ab2..ae494da41 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/phemex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/phemex.js @@ -305,13 +305,13 @@ module.exports = class phemex extends Exchange { }); } - parseSafeFloat (value = undefined) { + parseSafeNumber (value = undefined) { if (value === undefined) { return value; } value = value.replace (',', ''); const parts = value.split (' '); - return this.safeFloat (parts, 0); + return this.safeNumber (parts, 0); } parseSwapMarket (market) { @@ -335,7 +335,9 @@ module.exports = class phemex extends Exchange { // "minPriceEp":5000, // "maxPriceEp":10000000000, // "maxOrderQty":1000000, - // "type":"Perpetual" + // "type":"Perpetual", + // "status":"Listed", + // "tipOrderQty":1000000, // "steps":"50", // "riskLimits":[ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000}, @@ -360,7 +362,7 @@ module.exports = class phemex extends Exchange { // } // const id = this.safeString (market, 'symbol'); - const baseId = this.safeString (market, 'baseCurrency', 'contractUnderlyingAssets'); + const baseId = this.safeString2 (market, 'baseCurrency', 'contractUnderlyingAssets'); const quoteId = this.safeString (market, 'quoteCurrency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); @@ -377,16 +379,16 @@ module.exports = class phemex extends Exchange { } const linear = !inverse; const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const priceScale = this.safeInteger (market, 'priceScale'); const ratioScale = this.safeInteger (market, 'ratioScale'); const valueScale = this.safeInteger (market, 'valueScale'); - const minPriceEp = this.safeFloat (market, 'minPriceEp'); - const maxPriceEp = this.safeFloat (market, 'maxPriceEp'); - const makerFeeRateEr = this.safeFloat (market, 'makerFeeRateEr'); - const takerFeeRateEr = this.safeFloat (market, 'takerFeeRateEr'); + const minPriceEp = this.safeNumber (market, 'minPriceEp'); + const maxPriceEp = this.safeNumber (market, 'maxPriceEp'); + const makerFeeRateEr = this.safeNumber (market, 'makerFeeRateEr'); + const takerFeeRateEr = this.safeNumber (market, 'takerFeeRateEr'); if (makerFeeRateEr !== undefined) { maker = this.fromEn (makerFeeRateEr, ratioScale, 0.00000001); } @@ -404,10 +406,11 @@ module.exports = class phemex extends Exchange { }, 'cost': { 'min': undefined, - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderQty')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderQty')), }, }; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -456,7 +459,9 @@ module.exports = class phemex extends Exchange { // "defaultMakerFee":"0.001", // "defaultMakerFeeEr":100000, // "baseQtyPrecision":6, - // "quoteQtyPrecision":2 + // "quoteQtyPrecision":2, + // "status":"Listed", + // "tipOrderQty":20 // } // const type = this.safeStringLower (market, 'type'); @@ -467,30 +472,31 @@ module.exports = class phemex extends Exchange { const inverse = undefined; const spot = true; const swap = false; - const taker = this.safeFloat (market, 'defaultTakerFee'); - const maker = this.safeFloat (market, 'defaultMakerFee'); + const taker = this.safeNumber (market, 'defaultTakerFee'); + const maker = this.safeNumber (market, 'defaultMakerFee'); const precision = { - 'amount': this.parseSafeFloat (this.safeString (market, 'baseTickSize')), - 'price': this.parseSafeFloat (this.safeString (market, 'quoteTickSize')), + 'amount': this.parseSafeNumber (this.safeString (market, 'baseTickSize')), + 'price': this.parseSafeNumber (this.safeString (market, 'quoteTickSize')), }; const limits = { 'amount': { 'min': precision['amount'], - 'max': this.parseSafeFloat (this.safeString (market, 'maxBaseOrderSize')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxBaseOrderSize')), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.parseSafeFloat (this.safeString (market, 'minOrderValue')), - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderValue')), + 'min': this.parseSafeNumber (this.safeString (market, 'minOrderValue')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderValue')), }, }; const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -680,8 +686,8 @@ module.exports = class phemex extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const valueScale = this.safeInteger (currency, 'valueScale'); - const minValueEv = this.safeFloat (currency, 'minValueEv'); - const maxValueEv = this.safeFloat (currency, 'maxValueEv'); + const minValueEv = this.safeNumber (currency, 'minValueEv'); + const maxValueEv = this.safeNumber (currency, 'maxValueEv'); let minAmount = undefined; let maxAmount = undefined; let precision = undefined; @@ -731,12 +737,12 @@ module.exports = class phemex extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - let amount = this.safeFloat (bidask, amountKey); + let amount = this.safeNumber (bidask, amountKey); if (market['spot']) { amount = this.fromEv (amount, market); } return [ - this.fromEp (this.safeFloat (bidask, priceKey), market), + this.fromEp (this.safeNumber (bidask, priceKey), market), amount, ]; } @@ -870,16 +876,16 @@ module.exports = class phemex extends Exchange { // let baseVolume = undefined; if ((market !== undefined) && market['spot']) { - baseVolume = this.fromEv (this.safeFloat (ohlcv, 7), market); + baseVolume = this.fromEv (this.safeNumber (ohlcv, 7), market); } else { baseVolume = this.safeInteger (ohlcv, 7); } return [ this.safeTimestamp (ohlcv, 0), - this.fromEp (this.safeFloat (ohlcv, 3), market), - this.fromEp (this.safeFloat (ohlcv, 4), market), - this.fromEp (this.safeFloat (ohlcv, 5), market), - this.fromEp (this.safeFloat (ohlcv, 6), market), + this.fromEp (this.safeNumber (ohlcv, 3), market), + this.fromEp (this.safeNumber (ohlcv, 4), market), + this.fromEp (this.safeNumber (ohlcv, 5), market), + this.fromEp (this.safeNumber (ohlcv, 6), market), baseVolume, ]; } @@ -972,11 +978,11 @@ module.exports = class phemex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.000001); - const last = this.fromEp (this.safeFloat (ticker, 'lastEp'), market); - const quoteVolume = this.fromEp (this.safeFloat (ticker, 'turnoverEv'), market); - let baseVolume = this.safeFloat (ticker, 'volume'); + const last = this.fromEp (this.safeNumber (ticker, 'lastEp'), market); + const quoteVolume = this.fromEp (this.safeNumber (ticker, 'turnoverEv'), market); + let baseVolume = this.safeNumber (ticker, 'volume'); if (baseVolume === undefined) { - baseVolume = this.fromEv (this.safeFloat (ticker, 'volumeEv')); + baseVolume = this.fromEv (this.safeNumber (ticker, 'volumeEv')); } let vwap = undefined; if ((market !== undefined) && (market['spot'])) { @@ -985,7 +991,7 @@ module.exports = class phemex extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.fromEp (this.safeFloat (ticker, 'openEp'), market); + const open = this.fromEp (this.safeNumber (ticker, 'openEp'), market); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -997,11 +1003,11 @@ module.exports = class phemex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.fromEp (this.safeFloat (ticker, 'highEp'), market), - 'low': this.fromEp (this.safeFloat (ticker, 'lowEp'), market), - 'bid': this.fromEp (this.safeFloat (ticker, 'bidEp'), market), + 'high': this.fromEp (this.safeNumber (ticker, 'highEp'), market), + 'low': this.fromEp (this.safeNumber (ticker, 'lowEp'), market), + 'bid': this.fromEp (this.safeNumber (ticker, 'bidEp'), market), 'bidVolume': undefined, - 'ask': this.fromEp (this.safeFloat (ticker, 'askEp'), market), + 'ask': this.fromEp (this.safeNumber (ticker, 'askEp'), market), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -1192,8 +1198,8 @@ module.exports = class phemex extends Exchange { id = this.safeString (trade, tradeLength - 4); } side = this.safeStringLower (trade, tradeLength - 3); - price = this.fromEp (this.safeFloat (trade, tradeLength - 2), market); - amount = this.fromEv (this.safeFloat (trade, tradeLength - 1), market); + price = this.fromEp (this.safeNumber (trade, tradeLength - 2), market); + amount = this.fromEv (this.safeNumber (trade, tradeLength - 1), market); if (market['spot']) { if ((price !== undefined) && (amount !== undefined)) { cost = price * amount; @@ -1209,14 +1215,14 @@ module.exports = class phemex extends Exchange { if (execStatus === 'MakerFill') { takerOrMaker = 'maker'; } - price = this.fromEp (this.safeFloat (trade, 'execPriceEp'), market); - amount = this.fromEv (this.safeFloat (trade, 'execBaseQtyEv'), market); - amount = this.safeFloat (trade, 'execQty', amount); - cost = this.fromEv (this.safeFloat2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); - const feeCost = this.fromEv (this.safeFloat (trade, 'execFeeEv'), market); + price = this.fromEp (this.safeNumber (trade, 'execPriceEp'), market); + amount = this.fromEv (this.safeNumber (trade, 'execBaseQtyEv'), market); + amount = this.safeNumber (trade, 'execQty', amount); + cost = this.fromEv (this.safeNumber2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); + const feeCost = this.fromEv (this.safeNumber (trade, 'execFeeEv'), market); if (feeCost !== undefined) { let feeRate = undefined; - let feeRateEr = this.safeFloat (trade, 'feeRateEr'); + let feeRateEr = this.safeNumber (trade, 'feeRateEr'); if (feeRateEr < 0) { feeRateEr = Math.abs (feeRateEr); feeRate = this.fromEr (feeRateEr, market); @@ -1292,9 +1298,9 @@ module.exports = class phemex extends Exchange { const currency = this.safeValue (this.currencies, code, {}); const scale = this.safeInteger (currency, 'valueScale', 8); const account = this.account (); - const balanceEv = this.safeFloat (balance, 'balanceEv'); - const lockedTradingBalanceEv = this.safeFloat (balance, 'lockedTradingBalanceEv'); - const lockedWithdrawEv = this.safeFloat (balance, 'lockedWithdrawEv'); + const balanceEv = this.safeNumber (balance, 'balanceEv'); + const lockedTradingBalanceEv = this.safeNumber (balance, 'lockedTradingBalanceEv'); + const lockedWithdrawEv = this.safeNumber (balance, 'lockedWithdrawEv'); const total = this.fromEn (balanceEv, scale, scale, DECIMAL_PLACES); const lockedTradingBalance = this.fromEn (lockedTradingBalanceEv, scale, scale, DECIMAL_PLACES); const lockedWithdraw = this.fromEn (lockedWithdrawEv, scale, scale, DECIMAL_PLACES); @@ -1388,8 +1394,8 @@ module.exports = class phemex extends Exchange { const code = this.safeCurrencyCode (currencyId); const currency = this.currency (code); const account = this.account (); - const accountBalanceEv = this.safeFloat (balance, 'accountBalanceEv'); - const totalUsedBalanceEv = this.safeFloat (balance, 'totalUsedBalanceEv'); + const accountBalanceEv = this.safeNumber (balance, 'accountBalanceEv'); + const totalUsedBalanceEv = this.safeNumber (balance, 'totalUsedBalanceEv'); const valueScale = this.safeInteger (currency, 'valueScale', 8); account['total'] = this.fromEn (accountBalanceEv, valueScale, valueScale, DECIMAL_PLACES); account['used'] = this.fromEn (totalUsedBalanceEv, valueScale, valueScale, DECIMAL_PLACES); @@ -1621,21 +1627,21 @@ module.exports = class phemex extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let price = this.fromEp (this.safeFloat (order, 'priceEp'), market); + let price = this.fromEp (this.safeNumber (order, 'priceEp'), market); if (price === 0) { price = undefined; } - const amount = this.fromEv (this.safeFloat (order, 'baseQtyEv'), market); - const remaining = this.fromEv (this.safeFloat (order, 'leavesBaseQtyEv'), market); - let filled = this.fromEv (this.safeFloat (order, 'cumBaseQtyEv'), market); - const cost = this.fromEv (this.safeFloat (order, 'quoteQtyEv'), market); - const average = this.fromEp (this.safeFloat (order, 'avgPriceEp'), market); + const amount = this.fromEv (this.safeNumber (order, 'baseQtyEv'), market); + const remaining = this.fromEv (this.safeNumber (order, 'leavesBaseQtyEv'), market); + let filled = this.fromEv (this.safeNumber (order, 'cumBaseQtyEv'), market); + const cost = this.fromEv (this.safeNumber (order, 'quoteQtyEv'), market); + const average = this.fromEp (this.safeNumber (order, 'avgPriceEp'), market); const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'ordType')); const timestamp = this.safeIntegerProduct2 (order, 'actionTimeNs', 'createTimeNs', 0.000001); let fee = undefined; - const feeCost = this.fromEv (this.safeFloat (order, 'cumFeeEv'), market); + const feeCost = this.fromEv (this.safeNumber (order, 'cumFeeEv'), market); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1648,7 +1654,7 @@ module.exports = class phemex extends Exchange { } } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.fromEp (this.safeFloat (order, 'stopPxEp', market)); + const stopPrice = this.fromEp (this.safeNumber (order, 'stopPxEp', market)); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -1721,18 +1727,18 @@ module.exports = class phemex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'orderType')); - const price = this.fromEp (this.safeFloat (order, 'priceEp'), market); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); + const price = this.fromEp (this.safeNumber (order, 'priceEp'), market); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); const timestamp = this.safeIntegerProduct (order, 'actionTimeNs', 0.000001); - const cost = this.safeFloat (order, 'cumValue'); + const cost = this.safeNumber (order, 'cumValue'); let lastTradeTimestamp = this.safeIntegerProduct (order, 'transactTimeNs', 0.000001); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -1807,7 +1813,7 @@ module.exports = class phemex extends Exchange { } request['qtyType'] = qtyType; if (qtyType === 'ByQuote') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); params = this.omit (params, 'cost'); if (this.options['createOrderByQuoteRequiresPrice']) { if (price !== undefined) { @@ -1827,7 +1833,7 @@ module.exports = class phemex extends Exchange { if (type === 'Limit') { request['priceEp'] = this.toEp (price, market); } - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice !== undefined) { request['stopPxEp'] = this.toEp (stopPrice, market); } @@ -2335,7 +2341,7 @@ module.exports = class phemex extends Exchange { const code = currency['code']; const timestamp = this.safeInteger2 (transaction, 'createdAt', 'submitedAt'); let type = this.safeStringLower (transaction, 'type'); - const feeCost = this.fromEn (this.safeFloat (transaction, 'feeEv'), currency['valueScale'], currency['precision']); + const feeCost = this.fromEn (this.safeNumber (transaction, 'feeEv'), currency['valueScale'], currency['precision']); let fee = undefined; if (feeCost !== undefined) { type = 'withdrawal'; @@ -2345,7 +2351,7 @@ module.exports = class phemex extends Exchange { }; } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.fromEn (this.safeFloat (transaction, 'amountEv'), currency['valueScale'], currency['precision']); + const amount = this.fromEn (this.safeNumber (transaction, 'amountEv'), currency['valueScale'], currency['precision']); return { 'info': transaction, 'id': id, @@ -2367,7 +2373,7 @@ module.exports = class phemex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.safeString (params, 'code'); const request = {}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/poloniex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/poloniex.js index 30eee15c9..fbb6447ad 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/poloniex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/poloniex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -113,6 +114,7 @@ module.exports = class poloniex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', // starting from Jan 8 2020 'maker': 0.0009, 'taker': 0.0009, @@ -207,24 +209,6 @@ module.exports = class poloniex extends Exchange { }); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - parseOHLCV (ohlcv, market = undefined) { // // { @@ -240,11 +224,11 @@ module.exports = class poloniex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'date'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'quoteVolume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'quoteVolume'), ]; } @@ -337,11 +321,11 @@ module.exports = class poloniex extends Exchange { const balance = this.safeValue (response, currencyId, {}); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onOrders'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFees (params = {}) { @@ -359,8 +343,8 @@ module.exports = class poloniex extends Exchange { // return { 'info': fees, - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), 'withdraw': {}, 'deposit': {}, }; @@ -418,8 +402,8 @@ module.exports = class poloniex extends Exchange { let open = undefined; let change = undefined; let average = undefined; - const last = this.safeFloat (ticker, 'last'); - const relativeChange = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const relativeChange = this.safeNumber (ticker, 'percentChange'); if (relativeChange !== -1) { open = last / this.sum (1, relativeChange); change = last - open; @@ -429,11 +413,11 @@ module.exports = class poloniex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24hr'), - 'low': this.safeFloat (ticker, 'low24hr'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high24hr'), + 'low': this.safeNumber (ticker, 'low24hr'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -443,8 +427,8 @@ module.exports = class poloniex extends Exchange { 'change': change, 'percentage': relativeChange * 100, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -485,7 +469,7 @@ module.exports = class poloniex extends Exchange { const code = this.safeCurrencyCode (id); const active = (currency['delisted'] === 0) && !currency['disabled']; const numericId = this.safeInteger (currency, 'id'); - const fee = this.safeFloat (currency, 'txFee'); + const fee = this.safeNumber (currency, 'txFee'); result[code] = { 'id': id, 'numericId': numericId, @@ -576,13 +560,18 @@ module.exports = class poloniex extends Exchange { } const side = this.safeString (trade, 'type'); let fee = undefined; - const price = this.safeFloat (trade, 'rate'); - const cost = this.safeFloat (trade, 'total'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const feeDisplay = this.safeString (trade, 'feeDisplay'); if (feeDisplay !== undefined) { const parts = feeDisplay.split (' '); - const feeCost = this.safeFloat (parts, 0); + const feeCost = this.safeNumber (parts, 0); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -601,7 +590,7 @@ module.exports = class poloniex extends Exchange { } } let takerOrMaker = undefined; - const takerAdjustment = this.safeFloat (trade, 'takerAdjustment'); + const takerAdjustment = this.safeNumber (trade, 'takerAdjustment'); if (takerAdjustment !== undefined) { takerOrMaker = 'taker'; } @@ -847,9 +836,9 @@ module.exports = class poloniex extends Exchange { if (resultingTrades !== undefined) { trades = this.parseTrades (resultingTrades, market); } - const price = this.safeFloat2 (order, 'price', 'rate'); - let remaining = this.safeFloat (order, 'amount'); - let amount = this.safeFloat (order, 'startingAmount'); + const price = this.safeNumber2 (order, 'price', 'rate'); + let remaining = this.safeNumber (order, 'amount'); + let amount = this.safeNumber (order, 'startingAmount'); let filled = undefined; let cost = 0; if (amount !== undefined) { @@ -899,7 +888,7 @@ module.exports = class poloniex extends Exchange { } const id = this.safeString (order, 'orderNumber'); let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -1396,11 +1385,11 @@ module.exports = class poloniex extends Exchange { const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit'; const type = this.safeString (transaction, 'type', defaultType); const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'paymentID'); // according to https://poloniex.com/fees/ - const feeCost = this.safeFloat (transaction, 'fee', 0); + const feeCost = this.safeNumber (transaction, 'fee', 0); if (type === 'withdrawal') { // poloniex withdrawal amount includes the fee amount = amount - feeCost; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/probit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/probit.js index 522045f2c..2b551ca0a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/probit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/probit.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, BadResponse, BadRequest, InvalidOrder, InsufficientFunds, AuthenticationError, ArgumentsRequired, InvalidAddress, RateLimitExceeded, DDoSProtection, BadSymbol } = require ('./base/errors'); const { TRUNCATE, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -140,9 +141,11 @@ module.exports = class probit extends Exchange { }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', 'CBC': 'CryptoBharatCoin', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'HBC': 'Hybrid Bank Cash', 'UNI': 'UNICORN Token', }, @@ -191,11 +194,11 @@ module.exports = class probit extends Exchange { const costPrecision = this.safeInteger (market, 'cost_precision'); const precision = { 'amount': 1 / Math.pow (10, amountPrecision), - 'price': this.safeFloat (market, 'price_increment'), + 'price': this.safeNumber (market, 'price_increment'), 'cost': 1 / Math.pow (10, costPrecision), }; - const takerFeeRate = this.safeFloat (market, 'taker_fee_rate'); - const makerFeeRate = this.safeFloat (market, 'maker_fee_rate'); + const takerFeeRate = this.safeNumber (market, 'taker_fee_rate'); + const makerFeeRate = this.safeNumber (market, 'maker_fee_rate'); result.push ({ 'id': id, 'info': market, @@ -210,16 +213,16 @@ module.exports = class probit extends Exchange { 'maker': makerFeeRate / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_cost'), - 'max': this.safeFloat (market, 'max_cost'), + 'min': this.safeNumber (market, 'min_cost'), + 'max': this.safeNumber (market, 'max_cost'), }, }, }); @@ -306,7 +309,7 @@ module.exports = class probit extends Exchange { // [ { 'amount': '0.015', 'priority': 1, 'currency_id': 'ETH' }, {} ] for (let j = 0; j < withdrawalFees.length; j++) { const withdrawalFee = withdrawalFees[j]; - const amount = this.safeFloat (withdrawalFee, 'amount'); + const amount = this.safeNumber (withdrawalFee, 'amount'); const priority = this.safeInteger (withdrawalFee, 'priority'); if ((amount !== undefined) && (priority !== undefined)) { fees.push (withdrawalFee); @@ -314,7 +317,7 @@ module.exports = class probit extends Exchange { } const withdrawalFeesByPriority = this.sortBy (fees, 'priority'); const withdrawalFee = this.safeValue (withdrawalFeesByPriority, 0, {}); - const fee = this.safeFloat (withdrawalFee, 'amount'); + const fee = this.safeNumber (withdrawalFee, 'amount'); result[code] = { 'id': id, 'code': code, @@ -337,11 +340,11 @@ module.exports = class probit extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (platform, 'min_deposit_amount'), + 'min': this.safeNumber (platform, 'min_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (platform, 'min_withdrawal_amount'), + 'min': this.safeNumber (platform, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -371,11 +374,11 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (balance, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'total'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -427,14 +430,6 @@ module.exports = class probit extends Exchange { return this.parseTickers (data, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -482,8 +477,8 @@ module.exports = class probit extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); - const close = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); + const close = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); let percentage = undefined; let open = undefined; if (change !== undefined) { @@ -492,15 +487,15 @@ module.exports = class probit extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -642,16 +637,13 @@ module.exports = class probit extends Exchange { marketId = this.safeString (trade, 'market_id', marketId); const symbol = this.safeSymbol (marketId, market, '-'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'order_id'); - const feeCost = this.safeFloat (trade, 'fee_amount'); + const feeCost = this.safeNumber (trade, 'fee_amount'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency_id'); @@ -795,11 +787,11 @@ module.exports = class probit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'start_time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_volume'), ]; } @@ -898,37 +890,24 @@ module.exports = class probit extends Exchange { const marketId = this.safeString (order, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'time')); - let price = this.safeFloat (order, 'limit_price'); - const filled = this.safeFloat (order, 'filled_quantity'); - let remaining = this.safeFloat (order, 'open_quantity'); - const canceledAmount = this.safeFloat (order, 'cancelled_quantity'); + let price = this.safeNumber (order, 'limit_price'); + const filled = this.safeNumber (order, 'filled_quantity'); + let remaining = this.safeNumber (order, 'open_quantity'); + const canceledAmount = this.safeNumber (order, 'cancelled_quantity'); if (canceledAmount !== undefined) { remaining = this.sum (remaining, canceledAmount); } - const amount = this.safeFloat (order, 'quantity', this.sum (filled, remaining)); - let cost = this.safeFloat2 (order, 'filled_cost', 'cost'); + const amount = this.safeNumber (order, 'quantity', this.sum (filled, remaining)); + const cost = this.safeNumber2 (order, 'filled_cost', 'cost'); if (type === 'market') { price = undefined; } - let average = undefined; - if (filled !== undefined) { - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if (cost !== undefined) { - if (filled > 0) { - average = cost / filled; - } - } - } let clientOrderId = this.safeString (order, 'client_order_id'); if (clientOrderId === '') { clientOrderId = undefined; } const timeInForce = this.safeStringUpper (order, 'time_in_force'); - return { + return this.safeOrder ({ 'id': id, 'info': order, 'clientOrderId': clientOrderId, @@ -945,11 +924,11 @@ module.exports = class probit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'average': average, + 'average': undefined, 'cost': cost, 'fee': undefined, 'trades': undefined, - }; + }); } costToPrecision (symbol, cost) { @@ -979,7 +958,7 @@ module.exports = class probit extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -1104,16 +1083,6 @@ module.exports = class probit extends Exchange { return this.parseDepositAddresses (data); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { // In order to use this method // you need to allow API withdrawal from the API Settings Page, and @@ -1144,7 +1113,7 @@ module.exports = class probit extends Exchange { parseTransaction (transaction, currency = undefined) { const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'destination_tag'); const txid = this.safeString (transaction, 'hash'); @@ -1153,7 +1122,7 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (transaction, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined && feeCost !== 0) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/qtrade.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/qtrade.js index aa66545bf..d77b576c4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/qtrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/qtrade.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -179,11 +180,11 @@ module.exports = class qtrade extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_buy_value'), + 'min': this.safeNumber (market, 'minimum_buy_value'), 'max': undefined, }, 'price': { @@ -264,12 +265,12 @@ module.exports = class qtrade extends Exchange { 'info': currency, 'type': type, 'name': name, - 'fee': this.safeFloat (config, 'withdraw_fee'), + 'fee': this.safeNumber (config, 'withdraw_fee'), 'precision': this.safeInteger (currency, 'precision'), 'active': active, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimum_order'), + 'min': this.safeNumber (currency, 'minimum_order'), 'max': undefined, }, 'price': { @@ -304,11 +305,11 @@ module.exports = class qtrade extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'market_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'market_volume'), ]; } @@ -370,8 +371,8 @@ module.exports = class qtrade extends Exchange { const result = []; for (let j = 0; j < prices.length; j++) { const priceAsString = prices[j]; - const price = this.safeFloat (prices, j); - const amount = this.safeFloat (bidasks, priceAsString); + const price = this.safeNumber (prices, j); + const amount = this.safeNumber (bidasks, priceAsString); result.push ([ price, amount ]); } orderbook[side] = result; @@ -403,12 +404,12 @@ module.exports = class qtrade extends Exchange { const marketId = this.safeString (ticker, 'id_hr'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeIntegerProduct (ticker, 'last_change', 0.001); - const previous = this.safeFloat (ticker, 'day_open'); - const last = this.safeFloat (ticker, 'last'); - const day_change = this.safeFloat (ticker, 'day_change'); + const previous = this.safeNumber (ticker, 'day_open'); + const last = this.safeNumber (ticker, 'last'); + const day_change = this.safeNumber (ticker, 'day_change'); let percentage = undefined; let change = undefined; - let average = this.safeFloat (ticker, 'day_avg_price'); + let average = this.safeNumber (ticker, 'day_avg_price'); if (day_change !== undefined) { percentage = day_change * 100; if (previous !== undefined) { @@ -418,18 +419,18 @@ module.exports = class qtrade extends Exchange { if ((average === undefined) && (last !== undefined) && (previous !== undefined)) { average = this.sum (last, previous) / 2; } - const baseVolume = this.safeFloat (ticker, 'day_volume_market'); - const quoteVolume = this.safeFloat (ticker, 'day_volume_base'); + const baseVolume = this.safeNumber (ticker, 'day_volume_market'); + const quoteVolume = this.safeNumber (ticker, 'day_volume_base'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'day_high'), - 'low': this.safeFloat (ticker, 'day_low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'day_high'), + 'low': this.safeNumber (ticker, 'day_low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': previous, @@ -637,16 +638,16 @@ module.exports = class qtrade extends Exchange { const side = this.safeString (trade, 'side'); const marketId = this.safeString (trade, 'market_string'); const symbol = this.safeSymbol (marketId, market, '_'); - let cost = this.safeFloat2 (trade, 'base_volume', 'base_amount'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'market_amount', 'amount'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - if (price !== undefined) { - cost = price * amount; - } + let cost = this.safeNumber2 (trade, 'base_volume', 'base_amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'market_amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'base_fee'); + const feeCost = this.safeNumber (trade, 'base_fee'); if (feeCost !== undefined) { const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; fee = { @@ -703,7 +704,7 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); account['used'] = 0; result[code] = account; } @@ -713,10 +714,10 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -845,10 +846,9 @@ module.exports = class qtrade extends Exchange { side = this.safeString (parts, 0); orderType = this.safeString (parts, 1); } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'market_amount'); - let remaining = this.safeFloat (order, 'market_amount_remaining'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'market_amount'); + const remaining = this.safeNumber (order, 'market_amount_remaining'); const open = this.safeValue (order, 'open', false); const closeReason = this.safeString (order, 'close_reason'); let status = undefined; @@ -860,58 +860,21 @@ module.exports = class qtrade extends Exchange { status = 'closed'; } const marketId = this.safeString (order, 'market_string'); - const symbol = this.safeSymbol (marketId, market, '_'); + market = this.safeMarket (marketId, market, '_'); + const symbol = market['symbol']; const rawTrades = this.safeValue (order, 'trades', []); const parsedTrades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id, 'side': side, 'type': orderType, }); - const numTrades = parsedTrades.length; - let lastTradeTimestamp = undefined; - let feeCost = undefined; - let cost = undefined; - if (numTrades > 0) { - feeCost = 0; - cost = 0; - filled = 0; - remaining = amount; - for (let i = 0; i < parsedTrades.length; i++) { - const trade = parsedTrades[i]; - feeCost = this.sum (trade['fee']['cost'], feeCost); - lastTradeTimestamp = this.safeInteger (trade, 'timestamp'); - cost = this.sum (trade['cost'], cost); - filled = this.sum (trade['amount'], filled); - remaining = Math.max (0, remaining - trade['amount']); - } - } - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; - fee = { - 'currency': feeCurrencyCode, - 'cost': feeCost, - }; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let average = undefined; - if (filled !== undefined) { - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': orderType, 'timeInForce': undefined, @@ -919,15 +882,16 @@ module.exports = class qtrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, - 'fee': fee, - 'cost': cost, + 'fee': undefined, + 'fees': undefined, + 'cost': undefined, 'trades': parsedTrades, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -1396,7 +1360,7 @@ module.exports = class qtrade extends Exchange { const tagTo = tag; const cancelRequested = this.safeValue (transaction, 'cancel_requested'); const type = (cancelRequested === undefined) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); let status = this.parseTransactionStatus (this.safeString (transaction, 'status')); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/rightbtc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/rightbtc.js index d22048303..c1cc6bc9b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/rightbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/rightbtc.js @@ -185,8 +185,8 @@ module.exports = class rightbtc extends Exchange { return result; } - divideSafeFloat (x, key, divisor) { - const value = this.safeFloat (x, key); + divideSafeNumber (x, key, divisor) { + const value = this.safeNumber (x, key); if (value !== undefined) { return value / divisor; } @@ -196,12 +196,12 @@ module.exports = class rightbtc extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); - const last = this.divideSafeFloat (ticker, 'last', 1e8); - const high = this.divideSafeFloat (ticker, 'high', 1e8); - const low = this.divideSafeFloat (ticker, 'low', 1e8); - const bid = this.divideSafeFloat (ticker, 'buy', 1e8); - const ask = this.divideSafeFloat (ticker, 'sell', 1e8); - const baseVolume = this.divideSafeFloat (ticker, 'vol24h', 1e8); + const last = this.divideSafeNumber (ticker, 'last', 1e8); + const high = this.divideSafeNumber (ticker, 'high', 1e8); + const low = this.divideSafeNumber (ticker, 'low', 1e8); + const bid = this.divideSafeNumber (ticker, 'buy', 1e8); + const ask = this.divideSafeNumber (ticker, 'sell', 1e8); + const baseVolume = this.divideSafeNumber (ticker, 'vol24h', 1e8); return { 'symbol': symbol, 'timestamp': timestamp, @@ -305,9 +305,9 @@ module.exports = class rightbtc extends Exchange { let id = this.safeString (trade, 'tid'); id = this.safeString (trade, 'trade_id', id); const orderId = this.safeString (trade, 'order_id'); - const price = this.divideSafeFloat (trade, 'price', 1e8); - let amount = this.safeFloat (trade, 'amount'); - amount = this.safeFloat (trade, 'quantity', amount); + const price = this.divideSafeNumber (trade, 'price', 1e8); + let amount = this.safeNumber (trade, 'amount'); + amount = this.safeNumber (trade, 'quantity', amount); if (amount !== undefined) { amount = amount / 1e8; } @@ -404,8 +404,8 @@ module.exports = class rightbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); // https://github.com/ccxt/ccxt/issues/3873 - account['free'] = this.divideSafeFloat (balance, 'balance', 1e8); - account['used'] = this.divideSafeFloat (balance, 'frozen', 1e8); + account['free'] = this.divideSafeNumber (balance, 'balance', 1e8); + account['used'] = this.divideSafeNumber (balance, 'frozen', 1e8); result[code] = account; } return this.parseBalance (result); @@ -494,30 +494,18 @@ module.exports = class rightbtc extends Exchange { } else if ('transactTime' in order) { timestamp = order['transactTime']; } - let price = this.safeFloat2 (order, 'limit', 'price'); + let price = this.safeNumber2 (order, 'limit', 'price'); if (price !== undefined) { price = price / 1e8; } - const amount = this.divideSafeFloat (order, 'quantity', 1e8); - let filled = this.divideSafeFloat (order, 'filled_quantity', 1e8); - let remaining = this.divideSafeFloat (order, 'rest', 1e8); - const cost = this.divideSafeFloat (order, 'cost', 1e8); + const amount = this.divideSafeNumber (order, 'quantity', 1e8); + const filled = this.divideSafeNumber (order, 'filled_quantity', 1e8); + const remaining = this.divideSafeNumber (order, 'rest', 1e8); + const cost = this.divideSafeNumber (order, 'cost', 1e8); // lines 483-494 should be generalized into a base class method - if (amount !== undefined) { - if (remaining === undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - if (filled === undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } - } const type = 'limit'; const side = this.safeStringLower (order, 'side'); - const feeCost = this.divideSafeFloat (order, 'min_fee', 1e8); + const feeCost = this.divideSafeNumber (order, 'min_fee', 1e8); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -525,13 +513,13 @@ module.exports = class rightbtc extends Exchange { feeCurrency = market['quote']; } fee = { - 'rate': this.safeFloat (order, 'fee'), + 'rate': this.safeNumber (order, 'fee'), 'cost': feeCost, 'currency': feeCurrency, }; } const trades = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -553,7 +541,7 @@ module.exports = class rightbtc extends Exchange { 'fee': fee, 'trades': trades, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ripio.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ripio.js index b3a30607e..8155014d3 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ripio.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/ripio.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, BadSymbol, BadRequest, InvalidOrder, ArgumentsRequired, OrderNotFound, InsufficientFunds, DDoSProtection } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -149,12 +150,12 @@ module.exports = class ripio extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'min_amount'), - 'price': this.safeFloat (market, 'price_tick'), + 'amount': this.safeNumber (market, 'min_amount'), + 'price': this.safeNumber (market, 'price_tick'), }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -162,15 +163,15 @@ module.exports = class ripio extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_value'), + 'min': this.safeNumber (market, 'min_value'), 'max': undefined, }, }; const active = this.safeValue (market, 'enabled', true); const fees = this.safeValue (market, 'fees', []); const firstFee = this.safeValue (fees, 0, {}); - const maker = this.safeFloat (firstFee, 'maker_fee', 0.0); - const taker = this.safeFloat (firstFee, 'taker_fee', 0.0); + const maker = this.safeNumber (firstFee, 'maker_fee', 0.0); + const taker = this.safeNumber (firstFee, 'taker_fee', 0.0); result.push ({ 'id': id, 'symbol': symbol, @@ -277,18 +278,18 @@ module.exports = class ripio extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); const marketId = this.safeString (ticker, 'pair'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const average = this.safeFloat (ticker, 'avg'); + const last = this.safeNumber (ticker, 'last_price'); + const average = this.safeNumber (ticker, 'avg'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bid_volume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'ask_volume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bid_volume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'ask_volume'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -430,15 +431,14 @@ module.exports = class ripio extends Exchange { if (side !== undefined) { side = side.toLowerCase (); } - const price = this.safeFloat2 (trade, 'price', 'match_price'); - const amount = this.safeFloat2 (trade, 'amount', 'exchanged'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString2 (trade, 'price', 'match_price'); + const amountString = this.safeString2 (trade, 'amount', 'exchanged'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'pair'); market = this.safeMarket (marketId, market); - const feeCost = this.safeFloat (trade, takerOrMaker + '_fee'); + const feeCost = this.safeNumber (trade, takerOrMaker + '_fee'); const orderId = this.safeString (trade, takerOrMaker); let fee = undefined; if (feeCost !== undefined) { @@ -512,11 +512,11 @@ module.exports = class ripio extends Exchange { const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -775,16 +775,16 @@ module.exports = class ripio extends Exchange { // } // const id = this.safeString (order, 'order_id'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat (order, 'notional'); + const amount = this.safeNumber (order, 'amount'); + let cost = this.safeNumber (order, 'notional'); const type = this.safeStringLower (order, 'order_type'); const priceField = (type === 'market') ? 'fill_price' : 'limit_price'; - const price = this.safeFloat (order, priceField); + const price = this.safeNumber (order, priceField); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeTimestamp (order, 'created_at'); let average = this.safeValue (order, 'fill_price'); - let filled = this.safeFloat (order, 'filled'); + let filled = this.safeNumber (order, 'filled'); let remaining = undefined; const fills = this.safeValue (order, 'fills'); let trades = undefined; @@ -819,7 +819,7 @@ module.exports = class ripio extends Exchange { } const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); return { 'id': id, 'clientOrderId': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/southxchange.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/southxchange.js index d2bdd8cec..96ca247a0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/southxchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/southxchange.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -114,14 +115,14 @@ module.exports = class southxchange extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const deposited = this.safeFloat (balance, 'Deposited'); - const unconfirmed = this.safeFloat (balance, 'Unconfirmed'); + const deposited = this.safeString (balance, 'Deposited'); + const unconfirmed = this.safeString (balance, 'Unconfirmed'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'Available'); - account['total'] = this.sum (deposited, unconfirmed); + account['free'] = this.safeString (balance, 'Available'); + account['total'] = Precise.stringAdd (deposited, unconfirmed); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -139,16 +140,16 @@ module.exports = class southxchange extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'Last'); + const last = this.safeNumber (ticker, 'Last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'Bid'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -156,9 +157,9 @@ module.exports = class southxchange extends Exchange { 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'Variation24Hr'), + 'percentage': this.safeNumber (ticker, 'Variation24Hr'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume24Hr'), + 'baseVolume': this.safeNumber (ticker, 'Volume24Hr'), 'quoteVolume': undefined, 'info': ticker, }; @@ -192,14 +193,11 @@ module.exports = class southxchange extends Exchange { parseTrade (trade, market) { const timestamp = this.safeTimestamp (trade, 'At'); - const price = this.safeFloat (trade, 'Price'); - const amount = this.safeFloat (trade, 'Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'Price'); + const amountString = this.safeString (trade, 'Amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'Type'); let symbol = undefined; if (market !== undefined) { @@ -240,21 +238,13 @@ module.exports = class southxchange extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const timestamp = undefined; - const price = this.safeFloat (order, 'LimitPrice'); - const amount = this.safeFloat (order, 'OriginalAmount'); - const remaining = this.safeFloat (order, 'Amount'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - cost = price * amount; - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'LimitPrice'); + const amount = this.safeNumber (order, 'OriginalAmount'); + const remaining = this.safeNumber (order, 'Amount'); const type = 'limit'; const side = this.safeStringLower (order, 'Type'); const id = this.safeString (order, 'Code'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -269,15 +259,14 @@ module.exports = class southxchange extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'filled': filled, + 'cost': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -410,8 +399,8 @@ module.exports = class southxchange extends Exchange { const type = this.safeString (item, 'Type'); const ledgerEntryType = this.parseLedgerEntryType (type); const code = this.safeCurrencyCode (this.safeString (item, 'CurrencyCode'), currency); - let amount = this.safeFloat (item, 'Amount'); - const after = this.safeFloat (item, 'TotalBalance'); + let amount = this.safeNumber (item, 'Amount'); + const after = this.safeNumber (item, 'TotalBalance'); let before = undefined; if (amount !== undefined) { if (after !== undefined) { @@ -582,7 +571,7 @@ module.exports = class southxchange extends Exchange { // } // const id = this.safeString (transaction, 'MovementId'); - const amount = this.safeFloat (transaction, 'Amount'); + const amount = this.safeNumber (transaction, 'Amount'); const address = this.safeString (transaction, 'Address'); const addressTo = address; const addressFrom = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/stex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/stex.js index af2e256f3..f4979c48a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/stex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/stex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -186,6 +187,7 @@ module.exports = class stex extends Exchange { 'BITSW': 'BITS', 'BHD': 'Bithold', 'BTH': 'Bithereum', + 'MPH': 'Chasyr Token', 'SBTC': 'SBTCT', // SiamBitcoin }, 'options': { @@ -249,7 +251,7 @@ module.exports = class stex extends Exchange { // differentiated fees for each particular method const code = this.safeCurrencyCode (this.safeString (currency, 'code')); const precision = this.safeInteger (currency, 'precision'); - const fee = this.safeFloat (currency, 'withdrawal_fee_const'); // todo: redesign + const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign const active = this.safeValue (currency, 'active', true); result[code] = { 'id': id, @@ -266,11 +268,11 @@ module.exports = class stex extends Exchange { 'price': { 'min': Math.pow (10, -precision), 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (currency, 'minimum_deposit_amount'), + 'min': this.safeNumber (currency, 'minimum_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal_amount'), + 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'), 'max': undefined, }, }, @@ -331,11 +333,11 @@ module.exports = class stex extends Exchange { 'price': this.safeInteger (market, 'market_precision'), }; const active = this.safeValue (market, 'active'); - const minBuyPrice = this.safeFloat (market, 'min_buy_price'); - const minSellPrice = this.safeFloat (market, 'min_sell_price'); + const minBuyPrice = this.safeNumber (market, 'min_buy_price'); + const minSellPrice = this.safeNumber (market, 'min_sell_price'); const minPrice = Math.max (minBuyPrice, minSellPrice); - const buyFee = this.safeFloat (market, 'buy_fee_percent') / 100; - const sellFee = this.safeFloat (market, 'sell_fee_percent') / 100; + const buyFee = this.safeNumber (market, 'buy_fee_percent') / 100; + const sellFee = this.safeNumber (market, 'sell_fee_percent') / 100; const fee = Math.max (buyFee, sellFee); result.push ({ 'id': id, @@ -354,7 +356,7 @@ module.exports = class stex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_order_amount'), + 'min': this.safeNumber (market, 'min_order_amount'), 'max': undefined, }, 'price': { 'min': minPrice, 'max': undefined }, @@ -518,8 +520,8 @@ module.exports = class stex extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString2 (ticker, 'id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -532,11 +534,11 @@ module.exports = class stex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -546,20 +548,12 @@ module.exports = class stex extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volumeQuote'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volumeQuote'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker (params); @@ -625,11 +619,11 @@ module.exports = class stex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -704,12 +698,11 @@ module.exports = class stex extends Exchange { // const id = this.safeString (trade, 'id'); const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; @@ -822,11 +815,11 @@ module.exports = class stex extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen_balance'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -885,9 +878,9 @@ module.exports = class stex extends Exchange { const marketId = this.safeString2 (order, 'currency_pair_id', 'currency_pair_name'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (order, 'timestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'initial_amount'); - const filled = this.safeFloat (order, 'processed_amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'initial_amount'); + const filled = this.safeNumber (order, 'processed_amount'); let remaining = undefined; let cost = undefined; if (filled !== undefined) { @@ -917,7 +910,7 @@ module.exports = class stex extends Exchange { 'order': id, }); } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); const result = { 'info': order, 'id': id, @@ -948,7 +941,7 @@ module.exports = class stex extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'amount'); + const feeCost = this.safeNumber (fees[i], 'amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1532,13 +1525,13 @@ module.exports = class stex extends Exchange { code = currency['code']; } const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status')); const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts'); const updated = this.safeTimestamp (transaction, 'updated_ts'); const txid = this.safeString (transaction, 'txid'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'fee_currency_id', 'deposit_fee_currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1774,8 +1767,8 @@ module.exports = class stex extends Exchange { for (let i = 0; i < data.length; i++) { const id = this.safeString (data[i], 'id'); const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (data[i], 'withdrawal_fee_const'); - depositFees[code] = this.safeFloat (data[i], 'deposit_fee_const'); + withdrawFees[code] = this.safeNumber (data[i], 'withdrawal_fee_const'); + depositFees[code] = this.safeNumber (data[i], 'deposit_fee_const'); } return { 'withdraw': withdrawFees, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/Exchange/test.ticker.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/Exchange/test.ticker.js index 7d91ea0ba..201873531 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/Exchange/test.ticker.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/Exchange/test.ticker.js @@ -74,6 +74,7 @@ module.exports = (exchange, ticker, method, symbol) => { if (![ + 'bybit', 'coinmarketcap', 'xbtce', 'coss', diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/functions/test.number.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/functions/test.number.js index f2e5eedd3..23e9f7926 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/functions/test.number.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/functions/test.number.js @@ -1,6 +1,7 @@ 'use strict' const { numberToString, decimalToPrecision, ROUND, TRUNCATE, DECIMAL_PLACES, TICK_SIZE, PAD_WITH_ZERO, SIGNIFICANT_DIGITS, toWei, fromWei } = require ('../../../../ccxt'); +const Precise = require ('../../../base/Precise') const assert = require ('assert'); // ---------------------------------------------------------------------------- @@ -287,3 +288,58 @@ assert (decimalToPrecision ('1602000000000000000000', TRUNCATE, 3, SIGNIFICANT_D // throws (() => // decimalToPrecision ('0.01', TRUNCATE, -1, TICK_SIZE), // "TICK_SIZE cant be used with negative numPrecisionDigits") + +// ---------------------------------------------------------------------------- + +const w = '-1.123e-6'; +const x = '0.00000002'; +const y = '69696900000'; +const z = '0'; +const a = '1e8'; + +assert (Precise.stringMul (x, y) === '1393.938'); +assert (Precise.stringMul (y, x) === '1393.938'); +assert (Precise.stringAdd (x, y) === '69696900000.00000002'); +assert (Precise.stringAdd (y, x) === '69696900000.00000002'); +assert (Precise.stringSub (x, y) === '-69696899999.99999998'); +assert (Precise.stringSub (y, x) === '69696899999.99999998'); +assert (Precise.stringDiv (x, y, 1) === '0'); +assert (Precise.stringDiv (x, y) === '0'); +assert (Precise.stringDiv (x, y, 19) === '0.0000000000000000002'); +assert (Precise.stringDiv (x, y, 20) === '0.00000000000000000028'); +assert (Precise.stringDiv (x, y, 21) === '0.000000000000000000286'); +assert (Precise.stringDiv (x, y, 22) === '0.0000000000000000002869'); +assert (Precise.stringDiv (y, x) === '3484845000000000000'); + +assert (Precise.stringMul (x, w) === '-0.00000000000002246'); +assert (Precise.stringMul (w, x) === '-0.00000000000002246'); +assert (Precise.stringAdd (x, w) === '-0.000001103'); +assert (Precise.stringAdd (w, x) === '-0.000001103'); +assert (Precise.stringSub (x, w) === '0.000001143'); +assert (Precise.stringSub (w, x) === '-0.000001143'); +assert (Precise.stringDiv (x, w) === '-0.017809439002671415'); +assert (Precise.stringDiv (w, x) === '-56.15'); + +assert (Precise.stringMul (z, w) === '0'); +assert (Precise.stringMul (z, x) === '0'); +assert (Precise.stringMul (z, y) === '0'); +assert (Precise.stringMul (w, z) === '0'); +assert (Precise.stringMul (x, z) === '0'); +assert (Precise.stringMul (y, z) === '0'); +assert (Precise.stringAdd (z, w) === '-0.000001123'); +assert (Precise.stringAdd (z, x) === '0.00000002'); +assert (Precise.stringAdd (z, y) === '69696900000'); +assert (Precise.stringAdd (w, z) === '-0.000001123'); +assert (Precise.stringAdd (x, z) === '0.00000002'); +assert (Precise.stringAdd (y, z) === '69696900000'); + +assert (Precise.stringMul (x, a) === '2'); +assert (Precise.stringMul (a, x) === '2'); +assert (Precise.stringMul (y, a) === '6969690000000000000'); +assert (Precise.stringMul (a, y) === '6969690000000000000'); +assert (Precise.stringDiv (y, a) === '696.969'); +assert (Precise.stringDiv (y, a, -1) === '690'); +assert (Precise.stringDiv (y, a, 0) === '696'); +assert (Precise.stringDiv (y, a, 1) === '696.9'); +assert (Precise.stringDiv (y, a, 2) === '696.96'); +assert (Precise.stringDiv (a, y) === '0.001434784043479695'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/test.base.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/test.base.js index 0eb7fcffa..6068fa10a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/test.base.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/test/base/test.base.js @@ -167,7 +167,7 @@ describe ('ccxt base code', () => { const exchange = new Exchange ({ 'id': 'mock' }) const propsSeenBefore = index ( - ["isNode", "empty", "keys", "values", "extend", "clone", "index", "ordered", "unique", "keysort", "indexBy", "groupBy", "filterBy", "sortBy", "flatten", "pluck", "omit", "sum", "deepExtend", "uuid", "unCamelCase", "capitalize", "isNumber", "isArray", "isObject", "isString", "isStringCoercible", "isDictionary", "hasProps", "prop", "asFloat", "asInteger", "safeFloat", "safeInteger", "safeValue", "safeString", "decimal", "toFixed", "truncate", "truncateToString", "precisionFromString", "stringToBinary", "stringToBase64", "base64ToBinary", "base64ToString", "binaryToString", "binaryConcat", "urlencode", "rawencode", "urlencodeBase64", "hash", "hmac", "jwt", "time", "setTimeout_safe", "sleep", "TimedOut", "timeout", "throttle", "json", "unjson", "aggregate", "is_node", "index_by", "group_by", "filter_by", "sort_by", "deep_extend", "un_camel_case", "is_number", "is_array", "is_object", "is_string", "is_string_coercible", "is_dictionary", "has_props", "as_float", "as_integer", "safe_float", "safe_integer", "safe_value", "safe_string", "to_fixed", "truncate_to_string", "precision_from_string", "string_to_binary", "string_to_base64", "utf16To_base64", "base64To_binary", "base64To_string", "binary_to_string", "binary_concat", "urlencode_base64", "set_timeout_safe", "Timed_out", "encode", "decode", "userAgents", "headers", "proxy", "origin", "iso8601", "parse8601", "milliseconds", "microseconds", "seconds", "id", "enableRateLimit", "rateLimit", "parseJsonResponse", "substituteCommonCurrencyCodes", "parseBalanceFromOpenOrders", "verbose", "debug", "journal", "userAgent", "twofa", "timeframes", "hasPublicAPI", "hasPrivateAPI", "hasCORS", "hasDeposit", "hasFetchBalance", "hasFetchClosedOrders", "hasFetchCurrencies", "hasFetchMyTrades", "hasFetchOHLCV", "hasFetchOpenOrders", "hasFetchOrder", "hasFetchOrderBook", "hasFetchOrders", "hasFetchTicker", "hasFetchTickers", "hasFetchBidsAsks", "hasFetchTrades", "hasWithdraw", "hasCreateOrder", "hasCancelOrder", "apiKey", "secret", "uid", "login", "password", "requiredCredentials", "exceptions", "balance", "orderbooks", "tickers", "fees", "orders", "trades", "currencies", "last_http_response", "last_json_response", "arrayConcat", "market_id", "market_ids", "array_concat", "implode_params", "extract_params", "fetch_balance", "fetch_free_balance", "fetch_used_balance","fetch_total_balance", "fetch_l2_order_book", "fetch_order_book", "fetch_bids_asks", "fetch_tickers", "fetch_ticker", "fetch_trades", "fetch_order", "fetch_orders", "fetch_open_orders", "fetch_closed_orders", "fetch_order_status", "fetch_markets", "load_markets", "set_markets", "parse_balance", "parse_bid_ask", "parse_bids_asks", "parse_order_book", "parse_trades", "parse_orders", "parse_ohlcv", "parse_ohlcvs", "edit_limit_buy_order", "edit_limit_sell_order", "edit_limit_order", "edit_order", "create_limit_buy_order", "create_limit_sell_order", "create_market_buy_order", "create_market_sell_order", "create_order", "calculate_fee", "common_currency_code", "price_to_precision", "amount_to_precision", "amount_to_string", "fee_to_precision", "cost_to_precision", "constructor", "getMarket", "describe", "defaults", "nonce", "encodeURIComponent", "checkRequiredCredentials", "initRestRateLimiter", "defineRestApi", "fetch", "fetch2", "request", "handleErrors", "defaultErrorHandler", "handleRestErrors", "handleRestResponse", "setMarkets", "loadMarkets", "fetchBidsAsks", "fetchTickers", "fetchOrder", "fetchOrders", "fetchOpenOrders", "fetchClosedOrders", "fetchMyTrades", "fetchCurrencies", "fetchMarkets", "fetchOrderStatus", "account", "commonCurrencyCode", "currency", "market", "marketId", "marketIds", "symbol", "extractParams", "implodeParams", "url", "parseBidAsk", "parseBidsAsks", "fetchL2OrderBook", "parseOrderBook", "parseBalance", "fetchPartialBalance", "fetchFreeBalance", "fetchUsedBalance", "fetchTotalBalance", "filterBySinceLimit", "parseTrades", "parseOrders", "filterOrdersBySymbol", "parseOHLCV", "parseOHLCVs", "editLimitBuyOrder", "editLimitSellOrder", "editLimitOrder", "editOrder", "createLimitBuyOrder", "createLimitSellOrder", "createMarketBuyOrder", "createMarketSellOrder", "costToPrecision", "priceToPrecision", "amountToPrecision", "amountToLots", "feeToPrecision", "calculateFee", "Ymd", "YmdHMS"] + ["isNode", "empty", "keys", "values", "extend", "clone", "index", "ordered", "unique", "keysort", "indexBy", "groupBy", "filterBy", "sortBy", "flatten", "pluck", "omit", "sum", "deepExtend", "uuid", "unCamelCase", "capitalize", "isNumber", "isArray", "isObject", "isString", "isStringCoercible", "isDictionary", "hasProps", "prop", "asFloat", "asInteger", "safeFloat", "safeInteger", "safeValue", "safeString", "decimal", "toFixed", "truncate", "truncateToString", "precisionFromString", "stringToBinary", "stringToBase64", "base64ToBinary", "base64ToString", "binaryToString", "binaryConcat", "urlencode", "rawencode", "urlencodeBase64", "hash", "hmac", "jwt", "time", "setTimeout_safe", "sleep", "TimedOut", "timeout", "throttle", "json", "aggregate", "is_node", "index_by", "group_by", "filter_by", "sort_by", "deep_extend", "un_camel_case", "is_number", "is_array", "is_object", "is_string", "is_string_coercible", "is_dictionary", "has_props", "as_float", "as_integer", "safe_float", "safe_integer", "safe_value", "safe_string", "to_fixed", "truncate_to_string", "precision_from_string", "string_to_binary", "string_to_base64", "utf16To_base64", "base64To_binary", "base64To_string", "binary_to_string", "binary_concat", "urlencode_base64", "set_timeout_safe", "Timed_out", "encode", "decode", "userAgents", "headers", "proxy", "origin", "iso8601", "parse8601", "milliseconds", "microseconds", "seconds", "id", "enableRateLimit", "rateLimit", "parseJsonResponse", "substituteCommonCurrencyCodes", "parseBalanceFromOpenOrders", "verbose", "debug", "journal", "userAgent", "twofa", "timeframes", "hasPublicAPI", "hasPrivateAPI", "hasCORS", "hasDeposit", "hasFetchBalance", "hasFetchClosedOrders", "hasFetchCurrencies", "hasFetchMyTrades", "hasFetchOHLCV", "hasFetchOpenOrders", "hasFetchOrder", "hasFetchOrderBook", "hasFetchOrders", "hasFetchTicker", "hasFetchTickers", "hasFetchBidsAsks", "hasFetchTrades", "hasWithdraw", "hasCreateOrder", "hasCancelOrder", "apiKey", "secret", "uid", "login", "password", "requiredCredentials", "exceptions", "balance", "orderbooks", "tickers", "fees", "orders", "trades", "currencies", "last_http_response", "last_json_response", "arrayConcat", "market_id", "market_ids", "array_concat", "implode_params", "extract_params", "fetch_balance", "fetch_free_balance", "fetch_used_balance","fetch_total_balance", "fetch_l2_order_book", "fetch_order_book", "fetch_bids_asks", "fetch_tickers", "fetch_ticker", "fetch_trades", "fetch_order", "fetch_orders", "fetch_open_orders", "fetch_closed_orders", "fetch_order_status", "fetch_markets", "load_markets", "set_markets", "parse_balance", "parse_bid_ask", "parse_bids_asks", "parse_order_book", "parse_trades", "parse_orders", "parse_ohlcv", "parse_ohlcvs", "edit_limit_buy_order", "edit_limit_sell_order", "edit_limit_order", "edit_order", "create_limit_buy_order", "create_limit_sell_order", "create_market_buy_order", "create_market_sell_order", "create_order", "calculate_fee", "common_currency_code", "price_to_precision", "amount_to_precision", "amount_to_string", "fee_to_precision", "cost_to_precision", "constructor", "getMarket", "describe", "defaults", "nonce", "encodeURIComponent", "checkRequiredCredentials", "initRestRateLimiter", "defineRestApi", "fetch", "fetch2", "request", "handleErrors", "defaultErrorHandler", "handleRestErrors", "handleRestResponse", "setMarkets", "loadMarkets", "fetchBidsAsks", "fetchTickers", "fetchOrder", "fetchOrders", "fetchOpenOrders", "fetchClosedOrders", "fetchMyTrades", "fetchCurrencies", "fetchMarkets", "fetchOrderStatus", "account", "commonCurrencyCode", "currency", "market", "marketId", "marketIds", "symbol", "extractParams", "implodeParams", "url", "parseBidAsk", "parseBidsAsks", "fetchL2OrderBook", "parseOrderBook", "parseBalance", "fetchPartialBalance", "fetchFreeBalance", "fetchUsedBalance", "fetchTotalBalance", "filterBySinceLimit", "parseTrades", "parseOrders", "filterOrdersBySymbol", "parseOHLCV", "parseOHLCVs", "editLimitBuyOrder", "editLimitSellOrder", "editLimitOrder", "editOrder", "createLimitBuyOrder", "createLimitSellOrder", "createMarketBuyOrder", "createMarketSellOrder", "costToPrecision", "priceToPrecision", "amountToPrecision", "amountToLots", "feeToPrecision", "calculateFee", "Ymd", "YmdHMS"] ) const props = index (Object.getOwnPropertyNames (exchange).concat ( diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/therock.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/therock.js index 12217e2b2..88ccb385d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/therock.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/therock.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -171,8 +172,8 @@ module.exports = class therock extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const buy_fee = this.safeFloat (market, 'buy_fee'); - const sell_fee = this.safeFloat (market, 'sell_fee'); + const buy_fee = this.safeNumber (market, 'buy_fee'); + const sell_fee = this.safeNumber (market, 'sell_fee'); let taker = Math.max (buy_fee, sell_fee); taker = taker / 100; const maker = taker; @@ -193,11 +194,11 @@ module.exports = class therock extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_quantity_offer'), + 'min': this.safeNumber (market, 'minimum_quantity_offer'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'minimum_price_offer'), + 'min': this.safeNumber (market, 'minimum_price_offer'), 'max': undefined, }, 'cost': { @@ -221,11 +222,11 @@ module.exports = class therock extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'trading_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'trading_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -244,27 +245,27 @@ module.exports = class therock extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'close'), // previous day close, if any + 'previousClose': this.safeNumber (ticker, 'close'), // previous day close, if any 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_traded'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume_traded'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -339,14 +340,11 @@ module.exports = class therock extends Exchange { const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; let feeCost = undefined; const transactions = this.safeValue (trade, 'transactions', []); @@ -356,7 +354,7 @@ module.exports = class therock extends Exchange { if (feeCost === undefined) { feeCost = 0; } - feeCost = this.sum (feeCost, this.safeFloat (feeTransactions[i], 'price')); + feeCost = this.sum (feeCost, this.safeNumber (feeTransactions[i], 'price')); } if (feeCost !== undefined) { fee = { @@ -511,7 +509,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (item, 'price'); + const amount = this.safeNumber (item, 'price'); const timestamp = this.parse8601 (this.safeString (item, 'date')); const status = 'ok'; return { @@ -743,7 +741,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'price'); + const amount = this.safeNumber (transaction, 'price'); const timestamp = this.parse8601 (this.safeString (transaction, 'date')); const status = 'ok'; // todo parse tags @@ -918,15 +916,15 @@ module.exports = class therock extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'date')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'amount_unfilled'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amount_unfilled'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let trades = this.safeValue (order, 'trades'); let cost = undefined; let average = undefined; @@ -953,7 +951,7 @@ module.exports = class therock extends Exchange { cost = 0; } } - const stopPrice = this.safeFloat (order, 'conditional_price'); + const stopPrice = this.safeNumber (order, 'conditional_price'); return { 'id': id, 'clientOrderId': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidebit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidebit.js index acf65de25..05efc673a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidebit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidebit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -182,11 +183,11 @@ module.exports = class tidebit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -211,15 +212,15 @@ module.exports = class tidebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'ask': this.safeFloat (ticker, 'sell'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'ask': this.safeNumber (ticker, 'sell'), 'bidVolume': undefined, 'askVolume': undefined, 'vwap': undefined, @@ -230,7 +231,7 @@ module.exports = class tidebit extends Exchange { 'percentage': undefined, 'previousClose': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -264,9 +265,14 @@ module.exports = class tidebit extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -311,11 +317,11 @@ module.exports = class tidebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -401,18 +407,12 @@ module.exports = class tidebit extends Exchange { const id = this.safeString (order, 'id'); const type = this.safeString (order, 'ord_type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const filled = this.safeFloat (order, 'executed_volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - let cost = undefined; - if (price !== undefined) { - if (filled !== undefined) { - cost = price * filled; - } - } - const average = this.safeFloat (order, 'avg_price'); - return { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const filled = this.safeNumber (order, 'executed_volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -429,12 +429,12 @@ module.exports = class tidebit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': average, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidex.js index 0988a4ad1..65c0e6d9e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/tidex.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class tidex extends Exchange { describe () { @@ -83,6 +84,7 @@ module.exports = class tidex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.1 / 100, @@ -127,19 +129,48 @@ module.exports = class tidex extends Exchange { async fetchCurrencies (params = {}) { const response = await this.webGetCurrency (params); + // + // [ + // { + // "id":2, + // "symbol":"BTC", + // "type":2, + // "name":"Bitcoin", + // "amountPoint":8, + // "depositEnable":true, + // "depositMinAmount":0.0005, + // "withdrawEnable":true, + // "withdrawFee":0.0004, + // "withdrawMinAmount":0.0005, + // "settings":{ + // "Blockchain":"https://blockchair.com/bitcoin/", + // "TxUrl":"https://blockchair.com/bitcoin/transaction/{0}", + // "AddrUrl":"https://blockchair.com/bitcoin/address/{0}", + // "ConfirmationCount":3, + // "NeedMemo":false + // }, + // "visible":true, + // "isDelisted":false + // } + // ] + // const result = {}; for (let i = 0; i < response.length; i++) { const currency = response[i]; const id = this.safeString (currency, 'symbol'); - const precision = currency['amountPoint']; + const precision = this.safeInteger (currency, 'amountPoint'); const code = this.safeCurrencyCode (id); - let active = currency['visible'] === true; - const canWithdraw = currency['withdrawEnable'] === true; - const canDeposit = currency['depositEnable'] === true; + const visible = this.safeValue (currency, 'visible'); + let active = visible === true; + const withdrawEnable = this.safeValue (currency, 'withdrawEnable'); + const depositEnable = this.safeValue (currency, 'depositEnable'); + const canWithdraw = withdrawEnable === true; + const canDeposit = depositEnable === true; if (!canWithdraw || !canDeposit) { active = false; } const name = this.safeString (currency, 'name'); + const fee = this.safeNumber (currency, 'withdrawFee'); result[code] = { 'id': id, 'code': code, @@ -149,7 +180,7 @@ module.exports = class tidex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': currency['withdrawFee'], + 'fee': fee, }, 'deposit': { 'active': canDeposit, @@ -170,11 +201,11 @@ module.exports = class tidex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawMinAmount'), + 'min': this.safeNumber (currency, 'withdrawMinAmount'), 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'depositMinAmount'), + 'min': this.safeNumber (currency, 'depositMinAmount'), 'max': undefined, }, }, @@ -184,26 +215,25 @@ module.exports = class tidex extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615861869, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":3.0, + // "min_amount":0.001, + // "max_amount":1000000.0, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.1, + // }, + // }, + // } + // const markets = response['pairs']; const keys = Object.keys (markets); const result = []; @@ -220,19 +250,20 @@ module.exports = class tidex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }, }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -241,7 +272,7 @@ module.exports = class tidex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -262,11 +293,11 @@ module.exports = class tidex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (funds, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'value'); - account['used'] = this.safeFloat (balance, 'inOrders'); + account['free'] = this.safeString (balance, 'value'); + account['used'] = this.safeString (balance, 'inOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -338,16 +369,16 @@ module.exports = class tidex extends Exchange { timestamp = undefined; } } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -356,9 +387,9 @@ module.exports = class tidex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -406,16 +437,19 @@ module.exports = class tidex extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const orderId = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = 'limit'; // all trades are still limit trades let takerOrMaker = undefined; let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -434,12 +468,6 @@ module.exports = class tidex extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': orderId, @@ -495,17 +523,18 @@ module.exports = class tidex extends Exchange { let status = 'open'; let filled = 0.0; let remaining = amount; - if ('return' in response) { - id = this.safeString (response['return'], 'order_id'); + const returnResult = this.safeValue (response, 'return'); + if (returnResult !== undefined) { + id = this.safeString (returnResult, 'order_id'); if (id === '0') { - id = this.safeString (response['return'], 'init_order_id'); + id = this.safeString (returnResult, 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (returnResult, 'received', filled); + remaining = this.safeNumber (returnResult, 'remains', amount); } const timestamp = this.milliseconds (); - return { + return this.safeOrder ({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -515,7 +544,7 @@ module.exports = class tidex extends Exchange { 'type': type, 'side': side, 'price': price, - 'cost': price * filled, + 'cost': undefined, 'amount': amount, 'remaining': remaining, 'filled': filled, @@ -525,7 +554,7 @@ module.exports = class tidex extends Exchange { 'clientOrderId': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -554,23 +583,15 @@ module.exports = class tidex extends Exchange { const symbol = this.safeSymbol (marketId, market); let remaining = undefined; let amount = undefined; - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; + const price = this.safeNumber (order, 'rate'); if ('start_amount' in order) { - amount = this.safeFloat (order, 'start_amount'); - remaining = this.safeFloat (order, 'amount'); + amount = this.safeNumber (order, 'start_amount'); + remaining = this.safeNumber (order, 'amount'); } else { - remaining = this.safeFloat (order, 'amount'); - } - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } + remaining = this.safeNumber (order, 'amount'); } const fee = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -584,15 +605,15 @@ module.exports = class tidex extends Exchange { 'side': this.safeString (order, 'type'), 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/timex.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/timex.js index 4c71ac4ff..227f97553 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/timex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/timex.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, PermissionDenied, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, RateLimitExceeded, NotSupported, BadRequest, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class timex extends Exchange { describe () { @@ -450,11 +451,11 @@ module.exports = class timex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'totalBalance'); - account['used'] = this.safeFloat (balance, 'lockedBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + account['used'] = this.safeString (balance, 'lockedBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -815,7 +816,7 @@ module.exports = class timex extends Exchange { const result = this.safeValue (response, 0, {}); return { 'info': response, - 'maker': this.safeFloat (result, 'fee'), + 'maker': this.safeNumber (result, 'fee'), 'taker': undefined, }; } @@ -852,18 +853,18 @@ module.exports = class timex extends Exchange { 'amount': this.precisionFromString (this.safeString (market, 'quantityIncrement')), 'price': this.precisionFromString (this.safeString (market, 'tickSize')), }; - const amountIncrement = this.safeFloat (market, 'quantityIncrement'); - const minBase = this.safeFloat (market, 'baseMinSize'); + const amountIncrement = this.safeNumber (market, 'quantityIncrement'); + const minBase = this.safeNumber (market, 'baseMinSize'); const minAmount = Math.max (amountIncrement, minBase); - const priceIncrement = this.safeFloat (market, 'tickSize'); - const minCost = this.safeFloat (market, 'quoteMinSize'); + const priceIncrement = this.safeNumber (market, 'tickSize'); + const minCost = this.safeNumber (market, 'quoteMinSize'); const limits = { 'amount': { 'min': minAmount, 'max': undefined }, 'price': { 'min': priceIncrement, 'max': undefined }, 'cost': { 'min': Math.max (minCost, minAmount * priceIncrement), 'max': undefined }, }; - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); return { 'id': id, 'symbol': symbol, @@ -924,7 +925,7 @@ module.exports = class timex extends Exchange { const name = this.safeString (currency, 'name'); const precision = this.safeInteger (currency, 'decimals'); const active = this.safeValue (currency, 'active'); - // const fee = this.safeFloat (currency, 'withdrawalFee'); + // const fee = this.safeNumber (currency, 'withdrawalFee'); const feeString = this.safeString (currency, 'withdrawalFee'); const tradeDecimals = this.safeInteger (currency, 'tradeDecimals'); let fee = undefined; @@ -961,14 +962,6 @@ module.exports = class timex extends Exchange { }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // // { @@ -988,8 +981,8 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '/'); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -1005,11 +998,11 @@ module.exports = class timex extends Exchange { 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -1019,8 +1012,8 @@ module.exports = class timex extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'volumeQuote'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volumeQuote'), }; } @@ -1039,23 +1032,27 @@ module.exports = class timex extends Exchange { // fetchMyTrades, fetchOrder (private) // // { - // "fee": "0.3", - // "id": 100, - // "makerOrTaker": "MAKER", - // "makerOrderId": "string", - // "price": "0.017", - // "quantity": "0.3", + // "id": "7613414", + // "makerOrderId": "0x8420af060722f560098f786a2894d4358079b6ea5d14b395969ed77bc87a623a", + // "takerOrderId": "0x1235ef158a361815b54c9988b6241c85aedcbc1fe81caf8df8587d5ab0373d1a", + // "symbol": "LTCUSDT", // "side": "BUY", - // "symbol": "TIMEETH", - // "takerOrderId": "string", - // "timestamp": "2019-12-08T04:54:11.171Z" - // } + // "quantity": "0.2", + // "fee": "0.22685", + // "feeToken": "USDT", + // "price": "226.85", + // "makerOrTaker": "TAKER", + // "timestamp": "2021-04-09T15:39:45.608" + // } // const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeStringLower2 (trade, 'direction', 'side'); const takerOrMaker = this.safeStringLower (trade, 'makerOrTaker'); @@ -1064,18 +1061,14 @@ module.exports = class timex extends Exchange { orderId = this.safeString (trade, takerOrMaker + 'OrderId'); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); + const feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'feeToken')); if (feeCost !== undefined) { - const feeCurrency = (market === undefined) ? undefined : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrency, }; } - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = this.costToPrecision (symbol, amount * price); - } return { 'info': trade, 'id': id, @@ -1107,11 +1100,11 @@ module.exports = class timex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1142,14 +1135,12 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'filledQuantity'); - const canceledQuantity = this.safeFloat (order, 'cancelledQuantity'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'filledQuantity'); + const canceledQuantity = this.safeNumber (order, 'cancelledQuantity'); let status = undefined; if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0.0); if (filled >= amount) { status = 'closed'; } else if ((canceledQuantity !== undefined) && (canceledQuantity > 0)) { @@ -1158,30 +1149,19 @@ module.exports = class timex extends Exchange { status = 'open'; } } - const cost = parseFloat (this.costToPrecision (symbol, price * filled)); - const fee = undefined; - let lastTradeTimestamp = undefined; - let trades = undefined; - const rawTrades = this.safeValue (order, 'trades'); - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'order': id, - }); - } - if (trades !== undefined) { - const numTrades = trades.length; - if (numTrades > 0) { - lastTradeTimestamp = trades[numTrades - 1]['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'order': id, + 'type': type, + }); const clientOrderId = this.safeString (order, 'clientOrderId'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': undefined, @@ -1190,14 +1170,14 @@ module.exports = class timex extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/upbit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/upbit.js index 829aa6586..890c30126 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/upbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/upbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, PermissionDenied, AddressPending } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -229,9 +230,9 @@ module.exports = class upbit extends Exchange { } else if ((locked !== undefined) && locked) { active = false; } - const maxOnetimeWithdrawal = this.safeFloat (withdrawLimits, 'onetime'); - const maxDailyWithdrawal = this.safeFloat (withdrawLimits, 'daily', maxOnetimeWithdrawal); - const remainingDailyWithdrawal = this.safeFloat (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); + const maxOnetimeWithdrawal = this.safeNumber (withdrawLimits, 'onetime'); + const maxDailyWithdrawal = this.safeNumber (withdrawLimits, 'daily', maxOnetimeWithdrawal); + const remainingDailyWithdrawal = this.safeNumber (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); let maxWithdrawLimit = undefined; if (remainingDailyWithdrawal > 0) { maxWithdrawLimit = remainingDailyWithdrawal; @@ -247,11 +248,11 @@ module.exports = class upbit extends Exchange { 'code': code, 'name': code, 'active': active, - 'fee': this.safeFloat (currencyInfo, 'withdraw_fee'), + 'fee': this.safeNumber (currencyInfo, 'withdraw_fee'), 'precision': precision, 'limits': { 'withdraw': { - 'min': this.safeFloat (withdrawLimits, 'minimum'), + 'min': this.safeNumber (withdrawLimits, 'minimum'), 'max': maxWithdrawLimit, }, }, @@ -314,8 +315,8 @@ module.exports = class upbit extends Exchange { }; const state = this.safeString (marketInfo, 'state'); const active = (state === 'active'); - const bidFee = this.safeFloat (response, 'bid_fee'); - const askFee = this.safeFloat (response, 'ask_fee'); + const bidFee = this.safeNumber (response, 'bid_fee'); + const askFee = this.safeNumber (response, 'ask_fee'); const fee = Math.max (bidFee, askFee); return { 'info': response, @@ -331,7 +332,7 @@ module.exports = class upbit extends Exchange { 'taker': fee, 'limits': { 'amount': { - 'min': this.safeFloat (ask, 'min_total'), + 'min': this.safeNumber (ask, 'min_total'), 'max': undefined, }, 'price': { @@ -339,8 +340,8 @@ module.exports = class upbit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (bid, 'min_total'), - 'max': this.safeFloat (marketInfo, 'max_total'), + 'min': this.safeNumber (bid, 'min_total'), + 'max': this.safeNumber (marketInfo, 'max_total'), }, }, }; @@ -379,8 +380,8 @@ module.exports = class upbit extends Exchange { 'price': 8, }; const active = true; - const makerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); - const takerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); + const makerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); + const takerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); result.push ({ 'id': id, 'symbol': symbol, @@ -433,11 +434,11 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { @@ -540,30 +541,30 @@ module.exports = class upbit extends Exchange { const timestamp = this.safeInteger (ticker, 'trade_timestamp'); const marketId = this.safeString2 (ticker, 'market', 'code'); const symbol = this.safeSymbol (marketId, market, '-'); - const previous = this.safeFloat (ticker, 'prev_closing_price'); - const last = this.safeFloat (ticker, 'trade_price'); - const change = this.safeFloat (ticker, 'signed_change_price'); - const percentage = this.safeFloat (ticker, 'signed_change_rate'); + const previous = this.safeNumber (ticker, 'prev_closing_price'); + const last = this.safeNumber (ticker, 'trade_price'); + const change = this.safeNumber (ticker, 'signed_change_price'); + const percentage = this.safeNumber (ticker, 'signed_change_rate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price'), - 'low': this.safeFloat (ticker, 'low_price'), + 'high': this.safeNumber (ticker, 'high_price'), + 'low': this.safeNumber (ticker, 'low_price'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'opening_price'), + 'open': this.safeNumber (ticker, 'opening_price'), 'close': last, 'last': last, 'previousClose': previous, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'acc_trade_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'acc_trade_price_24h'), + 'baseVolume': this.safeNumber (ticker, 'acc_trade_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'acc_trade_price_24h'), 'info': ticker, }; } @@ -670,15 +671,13 @@ module.exports = class upbit extends Exchange { } else if (askOrBid === 'bid') { side = 'buy'; } - let cost = this.safeFloat (trade, 'funds'); - const price = this.safeFloat2 (trade, 'trade_price', 'price'); - const amount = this.safeFloat2 (trade, 'trade_volume', 'volume'); + let cost = this.safeNumber (trade, 'funds'); + const priceString = this.safeString2 (trade, 'trade_price', 'price'); + const amountString = this.safeString2 (trade, 'trade_volume', 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString2 (trade, 'market', 'code'); market = this.safeMarket (marketId, market); @@ -773,11 +772,11 @@ module.exports = class upbit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'candle_date_time_utc')), - this.safeFloat (ohlcv, 'opening_price'), - this.safeFloat (ohlcv, 'high_price'), - this.safeFloat (ohlcv, 'low_price'), - this.safeFloat (ohlcv, 'trade_price'), - this.safeFloat (ohlcv, 'candle_acc_trade_volume'), // base volume + this.safeNumber (ohlcv, 'opening_price'), + this.safeNumber (ohlcv, 'high_price'), + this.safeNumber (ohlcv, 'low_price'), + this.safeNumber (ohlcv, 'trade_price'), + this.safeNumber (ohlcv, 'candle_acc_trade_volume'), // base volume ]; } @@ -1046,7 +1045,7 @@ module.exports = class upbit extends Exchange { // } // const id = this.safeString (transaction, 'uuid'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = undefined; // not present in the data structure received from the exchange const tag = undefined; // not present in the data structure received from the exchange const txid = this.safeString (transaction, 'txid'); @@ -1059,7 +1058,7 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -1144,10 +1143,10 @@ module.exports = class upbit extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const status = this.parseOrderStatus (this.safeString (order, 'state')); let lastTradeTimestamp = undefined; - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - const filled = this.safeFloat (order, 'executed_volume'); + let price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const filled = this.safeNumber (order, 'executed_volume'); let cost = undefined; if (type === 'price') { type = 'market'; @@ -1156,7 +1155,7 @@ module.exports = class upbit extends Exchange { } let average = undefined; let fee = undefined; - let feeCost = this.safeFloat (order, 'paid_fee'); + let feeCost = this.safeNumber (order, 'paid_fee'); const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); let trades = this.safeValue (order, 'trades', []); @@ -1179,7 +1178,7 @@ module.exports = class upbit extends Exchange { cost = this.sum (cost, trade['cost']); if (getFeesFromTrades) { const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); + const tradeFeeCost = this.safeNumber (tradeFee, 'cost'); if (tradeFeeCost !== undefined) { feeCost = this.sum (feeCost, tradeFeeCost); } @@ -1321,16 +1320,6 @@ module.exports = class upbit extends Exchange { return this.parseOrder (response); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetDepositsCoinAddresses (params); diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vaultoro.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vaultoro.js deleted file mode 100644 index abc1ba387..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vaultoro.js +++ /dev/null @@ -1,203 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); - -// --------------------------------------------------------------------------- - -module.exports = class vaultoro extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'vaultoro', - 'name': 'Vaultoro', - 'countries': [ 'CH' ], - 'rateLimit': 1000, - 'version': '1', - 'has': { - 'CORS': true, - 'fetchMarkets': true, - 'fetchOrderBook': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'fetchTrades': true, - 'fetchTicker': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg', - 'api': 'https://api.vaultoro.com', - 'www': 'https://www.vaultoro.com', - 'doc': 'https://api.vaultoro.com', - }, - 'commonCurrencies': { - 'GLD': 'Gold', - }, - 'api': { - 'public': { - 'get': [ - 'bidandask', - 'buyorders', - 'latest', - 'latesttrades', - 'markets', - 'orderbook', - 'sellorders', - 'transactions/day', - 'transactions/hour', - 'transactions/month', - ], - }, - 'private': { - 'get': [ - 'balance', - 'mytrades', - 'orders', - ], - 'post': [ - 'buy/{symbol}/{type}', - 'cancel/{id}', - 'sell/{symbol}/{type}', - 'withdraw', - ], - }, - }, - }); - } - - async fetchMarkets (params = {}) { - const result = []; - const response = await this.publicGetMarkets (params); - const market = this.safeValue (response, 'data'); - const baseId = this.safeString (market, 'MarketCurrency'); - const quoteId = this.safeString (market, 'BaseCurrency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const id = this.safeString (market, 'MarketName'); - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'active': undefined, - 'precision': this.precision, - 'limits': this.limits, - }); - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetBalance (params); - const balances = this.safeValue (response, 'data'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency_code'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'cash'); - account['used'] = this.safeFloat (balance, 'reserved'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetOrderbook (params); - const orderbook = { - 'bids': response['data'][0]['b'], - 'asks': response['data'][1]['s'], - }; - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'Gold_Price', 'Gold_Amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'Time')); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const price = this.safeFloat (trade, 'Gold_Price'); - const amount = this.safeFloat (trade, 'Gold_Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } - return { - 'id': undefined, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': undefined, - 'side': undefined, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const response = await this.publicGetTransactionsDay (params); - return this.parseTrades (response, market, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const method = 'privatePost' + this.capitalize (side) + 'SymbolType'; - const request = { - 'symbol': market['quoteId'].toLowerCase (), - 'type': type, - 'gld': amount, - 'price': price || 1, - }; - const response = await this[method] (this.extend (request, params)); - return { - 'info': response, - 'id': response['data']['Order_ID'], - }; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - return await this.privatePostCancelId (this.extend (request, params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/'; - if (api === 'public') { - url += path; - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce (); - url += this.version + '/' + this.implodeParams (path, params); - const query = this.extend ({ - 'nonce': nonce, - 'apikey': this.apiKey, - }, this.omit (params, this.extractParams (path))); - url += '?' + this.urlencode (query); - headers = { - 'Content-Type': 'application/json', - 'X-Signature': this.hmac (this.encode (url), this.encode (this.secret)), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vcc.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vcc.js index bd3a9602d..5b182adcb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vcc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/vcc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, OrderNotFound, InvalidOrder, BadRequest, AuthenticationError, RateLimitExceeded, RequestTimeout, BadSymbol, AddressPending, PermissionDenied, InsufficientFunds } = require ('./base/errors'); const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -196,15 +197,15 @@ module.exports = class vcc extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, 'min'), + 'min': this.safeNumber (amountLimits, 'min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (priceLimits, 'min'), + 'min': this.safeNumber (priceLimits, 'min'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (costLimits, 'min'), + 'min': this.safeNumber (costLimits, 'min'), 'max': undefined, }, }, @@ -251,12 +252,12 @@ module.exports = class vcc extends Exchange { 'code': code, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': this.safeInteger (currency, 'decimal'), 'limits': { 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw'), - 'max': this.safeFloat (currency, 'max_withdraw'), + 'min': this.safeNumber (currency, 'min_withdraw'), + 'max': this.safeNumber (currency, 'max_withdraw'), }, }, }; @@ -279,8 +280,8 @@ module.exports = class vcc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } @@ -306,11 +307,11 @@ module.exports = class vcc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (data, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -328,11 +329,11 @@ module.exports = class vcc extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -421,10 +422,10 @@ module.exports = class vcc extends Exchange { // } // const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); - const open = this.safeFloat (ticker, 'open_price'); - const last = this.safeFloat (ticker, 'last_price'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); + const open = this.safeNumber (ticker, 'open_price'); + const last = this.safeNumber (ticker, 'last_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -441,11 +442,11 @@ module.exports = class vcc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -559,17 +560,17 @@ module.exports = class vcc extends Exchange { } market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'base_volume', 'quantity'); - let cost = this.safeFloat2 (trade, 'quote_volume', 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'base_volume', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber2 (trade, 'quote_volume', 'amount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const side = this.safeString2 (trade, 'type', 'trade_type'); const id = this.safeString2 (trade, 'trade_id', 'id'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -754,7 +755,7 @@ module.exports = class vcc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -762,7 +763,7 @@ module.exports = class vcc extends Exchange { const txid = this.safeString (transaction, 'transaction_id'); const tag = this.safeString (transaction, 'destination_tag'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1007,46 +1008,27 @@ module.exports = class vcc extends Exchange { const marketId = baseId + '_' + quoteId; market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'executed_quantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - let cost = this.safeFloat (order, 'ceiling'); + const cost = this.safeNumber (order, 'ceiling'); const id = this.safeString (order, 'id'); - let average = undefined; - let price = this.safeFloat (order, 'price'); - // in case of market order - if (!price) { - price = this.safeFloat (order, 'executed_price'); - average = price; - } - let remaining = this.safeFloat (order, 'remaining'); - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if (filled !== undefined) { - if ((amount !== undefined) && (remaining === undefined)) { - remaining = Math.max (0, amount - filled); - } - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((average === undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'executed_price'); + const remaining = this.safeNumber (order, 'remaining'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'trade_type'); const fee = { 'currency': market['quote'], - 'cost': this.safeFloat (order, 'fee'), - 'rate': this.safeFloat (order, 'fee_rate'), + 'cost': this.safeNumber (order, 'fee'), + 'rate': this.safeNumber (order, 'fee_rate'), }; let lastTradeTimestamp = undefined; if (updated !== created) { lastTradeTimestamp = updated; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': id, 'timestamp': created, @@ -1068,7 +1050,7 @@ module.exports = class vcc extends Exchange { 'fee': fee, 'trades': undefined, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/wavesexchange.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/wavesexchange.js index 139780062..bd422c073 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/wavesexchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/wavesexchange.js @@ -565,13 +565,13 @@ module.exports = class wavesexchange extends Exchange { symbol = market['symbol']; } const data = this.safeValue (ticker, 'data', {}); - const last = this.safeFloat (data, 'lastPrice'); - const low = this.safeFloat (data, 'low'); - const high = this.safeFloat (data, 'high'); - const vwap = this.safeFloat (data, 'weightedAveragePrice'); - const baseVolume = this.safeFloat (data, 'volume'); - const quoteVolume = this.safeFloat (data, 'quoteVolume'); - const open = this.safeValue (data, 'firstPrice'); + const last = this.safeNumber (data, 'lastPrice'); + const low = this.safeNumber (data, 'low'); + const high = this.safeNumber (data, 'high'); + const vwap = this.safeNumber (data, 'weightedAveragePrice'); + const baseVolume = this.safeNumber (data, 'volume'); + const quoteVolume = this.safeNumber (data, 'quoteVolume'); + const open = this.safeNumber (data, 'firstPrice'); let change = undefined; let average = undefined; let percentage = undefined; @@ -725,11 +725,11 @@ module.exports = class wavesexchange extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.parse8601 (this.safeString (data, 'time')), - this.safeFloat (data, 'open'), - this.safeFloat (data, 'high'), - this.safeFloat (data, 'low'), - this.safeFloat (data, 'close'), - this.safeFloat (data, 'volume', 0), + this.safeNumber (data, 'open'), + this.safeNumber (data, 'high'), + this.safeNumber (data, 'low'), + this.safeNumber (data, 'close'), + this.safeNumber (data, 'volume', 0), ]; } @@ -944,7 +944,7 @@ module.exports = class wavesexchange extends Exchange { } if (matcherFee === undefined) { const wavesPrecision = this.safeInteger (this.options, 'wavesPrecision', 8); - const rate = this.safeFloat (rates, matcherFeeAssetId); + const rate = this.safeNumber (rates, matcherFeeAssetId); const code = this.safeCurrencyCode (matcherFeeAssetId); const currency = this.currency (code); const newPrecison = Math.pow (10, wavesPrecision - currency['precision']); @@ -1354,7 +1354,7 @@ module.exports = class wavesexchange extends Exchange { const issueTransaction = this.safeValue (entry, 'issueTransaction'); const decimals = this.safeInteger (issueTransaction, 'decimals'); const currencyId = this.safeString (entry, 'assetId'); - const balance = this.safeFloat (entry, 'balance'); + const balance = this.safeNumber (entry, 'balance'); let code = undefined; if (currencyId in this.currencies_by_id) { code = this.safeCurrencyCode (currencyId); @@ -1384,7 +1384,7 @@ module.exports = class wavesexchange extends Exchange { if (!(code in result)) { result[code] = this.account (); } - const amount = this.safeFloat (reservedBalance, currencyId); + const amount = this.safeNumber (reservedBalance, currencyId); result[code]['used'] = this.currencyFromPrecision (code, amount); } const wavesRequest = { @@ -1397,7 +1397,7 @@ module.exports = class wavesexchange extends Exchange { // "balance": 909085978 // } result['WAVES'] = this.safeValue (result, 'WAVES', {}); - result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeFloat (wavesTotal, 'balance')); + result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeNumber (wavesTotal, 'balance')); const codes = Object.keys (result); for (let i = 0; i < codes.length; i++) { const code = codes[i]; @@ -1489,8 +1489,8 @@ module.exports = class wavesexchange extends Exchange { const datetime = this.safeString (data, 'timestamp'); const timestamp = this.parse8601 (datetime); const id = this.safeString (data, 'id'); - const price = this.safeFloat (data, 'price'); - const amount = this.safeFloat (data, 'amount'); + const price = this.safeNumber (data, 'price'); + const amount = this.safeNumber (data, 'amount'); const order1 = this.safeValue (data, 'order1'); const order2 = this.safeValue (data, 'order2'); let order = undefined; @@ -1514,7 +1514,7 @@ module.exports = class wavesexchange extends Exchange { cost = price * amount; } const fee = { - 'cost': this.safeFloat (data, 'fee'), + 'cost': this.safeNumber (data, 'fee'), 'currency': this.safeCurrencyCode (this.safeString (order, 'matcherFeeAssetId', 'WAVES')), }; return { @@ -1596,7 +1596,7 @@ module.exports = class wavesexchange extends Exchange { const withdrawAddress = await this.privateGetWithdrawAddressesCurrencyAddress (withdrawAddressRequest); const currency = this.safeValue (withdrawAddress, 'currency'); const allowedAmount = this.safeValue (currency, 'allowed_amount'); - const minimum = this.safeFloat (allowedAmount, 'min'); + const minimum = this.safeNumber (allowedAmount, 'min'); if (amount <= minimum) { throw new BadRequest (this.id + ' ' + code + ' withdraw failed, amount ' + amount.toString () + ' must be greater than the minimum allowed amount of ' + minimum.toString ()); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/whitebit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/whitebit.js index 9e4418141..769cd5b8b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/whitebit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/whitebit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeNotAvailable, ExchangeError, DDoSProtection, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,7 +165,7 @@ module.exports = class whitebit extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -172,7 +173,7 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minTotal'), + 'min': this.safeNumber (market, 'minTotal'), 'max': undefined, }, }, @@ -237,8 +238,8 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -250,8 +251,8 @@ module.exports = class whitebit extends Exchange { const response = await this.publicV2GetFee (params); const fees = this.safeValue (response, 'result'); return { - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), }; } @@ -321,8 +322,8 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let change = undefined; if (percentage !== undefined) { change = this.numberToString (percentage * 0.01); @@ -331,22 +332,22 @@ module.exports = class whitebit extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'deal'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'deal'), 'info': ticker, }; } @@ -514,8 +515,11 @@ module.exports = class whitebit extends Exchange { } else { timestamp = parseInt (timestamp * 1000); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'volume'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'volume'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const id = this.safeString2 (trade, 'id', 'tradeId'); let side = this.safeString (trade, 'type'); if (side === undefined) { @@ -526,10 +530,6 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined && price !== undefined) { - cost = amount * price; - } return { 'info': trade, 'timestamp': timestamp, @@ -599,11 +599,11 @@ module.exports = class whitebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 5), // volume ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xbtce.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xbtce.js index e0d137f67..c8cabae42 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xbtce.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xbtce.js @@ -152,14 +152,13 @@ module.exports = class xbtce extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'FreeAmount'), - 'used': this.safeFloat (balance, 'LockedAmount'), - 'total': this.safeFloat (balance, 'Amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'FreeAmount'); + account['used'] = this.safeString (balance, 'LockedAmount'); + account['total'] = this.safeString (balance, 'Amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -271,11 +270,11 @@ module.exports = class xbtce extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeInteger (ohlcv, 'Timestamp'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xena.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xena.js index 2facd429b..e55a5332b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xena.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/xena.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, InsufficientFunds, InvalidAddress, BadSymbol, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class xena extends Exchange { describe () { @@ -277,8 +278,8 @@ module.exports = class xena extends Exchange { 'price': pricePrecision, 'amount': 0, }; - const maxCost = this.safeFloat (market, 'maxOrderQty'); - const minCost = this.safeFloat (market, 'minOrderQuantity'); + const maxCost = this.safeNumber (market, 'maxOrderQty'); + const minCost = this.safeNumber (market, 'minOrderQuantity'); const limits = { 'amount': { 'min': undefined, @@ -363,7 +364,7 @@ module.exports = class xena extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (withdraw, 'commission'), + 'fee': this.safeNumber (withdraw, 'commission'), 'precision': precision, 'limits': { 'amount': { @@ -379,7 +380,7 @@ module.exports = class xena extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'minAmount'), + 'min': this.safeNumber (withdraw, 'minAmount'), 'max': undefined, }, }, @@ -407,8 +408,8 @@ module.exports = class xena extends Exchange { const timestamp = this.milliseconds (); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPx'); - const open = this.safeFloat (ticker, 'firstPx'); + const last = this.safeNumber (ticker, 'lastPx'); + const open = this.safeNumber (ticker, 'firstPx'); let percentage = undefined; let change = undefined; let average = undefined; @@ -419,18 +420,18 @@ module.exports = class xena extends Exchange { percentage = change / open * 100; } } - const buyVolume = this.safeFloat (ticker, 'buyVolume'); - const sellVolume = this.safeFloat (ticker, 'sellVolume'); + const buyVolume = this.safeNumber (ticker, 'buyVolume'); + const sellVolume = this.safeNumber (ticker, 'sellVolume'); const baseVolume = this.sum (buyVolume, sellVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPx'), - 'low': this.safeFloat (ticker, 'lowPx'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'highPx'), + 'low': this.safeNumber (ticker, 'lowPx'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -607,11 +608,11 @@ module.exports = class xena extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onHold'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onHold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTrade (trade, market = undefined) { @@ -665,20 +666,17 @@ module.exports = class xena extends Exchange { const orderId = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat2 (trade, 'lastPx', 'mdEntryPx'); - const amount = this.safeFloat2 (trade, 'lastQty', 'mdEntrySize'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'lastPx', 'mdEntryPx'); + const amountString = this.safeString2 (trade, 'lastQty', 'mdEntrySize'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (trade, 'commRate'); + const feeRate = this.safeNumber (trade, 'commRate'); fee = { 'cost': feeCost, 'rate': feeRate, @@ -793,15 +791,15 @@ module.exports = class xena extends Exchange { // const transactTime = this.safeInteger (ohlcv, 'transactTime'); const timestamp = parseInt (transactTime / 1000000); - const buyVolume = this.safeFloat (ohlcv, 'buyVolume'); - const sellVolume = this.safeFloat (ohlcv, 'sellVolume'); + const buyVolume = this.safeNumber (ohlcv, 'buyVolume'); + const sellVolume = this.safeNumber (ohlcv, 'sellVolume'); const volume = this.sum (buyVolume, sellVolume); return [ timestamp, - this.safeFloat (ohlcv, 'firstPx'), - this.safeFloat (ohlcv, 'highPx'), - this.safeFloat (ohlcv, 'lowPx'), - this.safeFloat (ohlcv, 'lastPx'), + this.safeNumber (ohlcv, 'firstPx'), + this.safeNumber (ohlcv, 'highPx'), + this.safeNumber (ohlcv, 'lowPx'), + this.safeNumber (ohlcv, 'lastPx'), volume, ]; } @@ -926,11 +924,10 @@ module.exports = class xena extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); - let cost = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); let side = this.safeStringLower (order, 'side'); if (side === '1') { side = 'buy'; @@ -947,12 +944,7 @@ module.exports = class xena extends Exchange { } else if (type === '4') { type = 'stop-limit'; } - if (cost === undefined) { - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -967,14 +959,14 @@ module.exports = class xena extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1027,7 +1019,7 @@ module.exports = class xena extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if ((type === 'stop') || (type === 'stop-limit')) { - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPx param for order type ' + type); } @@ -1106,12 +1098,12 @@ module.exports = class xena extends Exchange { if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); } - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx !== undefined) { request['stopPx'] = this.priceToPrecision (symbol, stopPx); params = this.omit (params, 'stopPx'); } - const capPrice = this.safeFloat (params, 'capPrice'); + const capPrice = this.safeNumber (params, 'capPrice'); if (capPrice !== undefined) { request['capPrice'] = this.priceToPrecision (symbol, capPrice); params = this.omit (params, 'capPrice'); @@ -1466,7 +1458,7 @@ module.exports = class xena extends Exchange { const address = this.safeString (transaction, 'address'); const addressFrom = undefined; const addressTo = address; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const fee = undefined; return { @@ -1563,7 +1555,7 @@ module.exports = class xena extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'kind')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); @@ -1575,11 +1567,11 @@ module.exports = class xena extends Exchange { timestamp = parseInt (timestamp / 1000000); } const fee = { - 'cost': this.safeFloat (item, 'commission'), + 'cost': this.safeNumber (item, 'commission'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/yobit.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/yobit.js index 0ab100f68..82d86ea71 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/yobit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/yobit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError, RateLimitExceeded } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -138,6 +139,7 @@ module.exports = class yobit extends Exchange { 'NAV': 'NavajoCoin', 'NBT': 'NiceBytes', 'OMG': 'OMGame', + 'ONX': 'Onix', 'PAC': '$PAC', 'PLAY': 'PlayCoin', 'PIVX': 'Darknet', @@ -236,15 +238,33 @@ module.exports = class yobit extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['total'] = this.safeFloat (total, currencyId); + account['free'] = this.safeString (free, currencyId); + account['total'] = this.safeString (total, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615856752, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":10000, + // "min_amount":0.0001, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.2, + // "fee_buyer":0.2, + // "fee_seller":0.2 + // }, + // }, + // } + // const markets = this.safeValue (response, 'pairs'); const keys = Object.keys (markets); const result = []; @@ -262,15 +282,15 @@ module.exports = class yobit extends Exchange { 'price': this.safeInteger (market, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }; const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }; const costLimits = { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }; const limits = { 'amount': amountLimits, @@ -279,6 +299,7 @@ module.exports = class yobit extends Exchange { }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -287,7 +308,7 @@ module.exports = class yobit extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -363,16 +384,16 @@ module.exports = class yobit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -381,9 +402,9 @@ module.exports = class yobit extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -432,15 +453,18 @@ module.exports = class yobit extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const order = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const type = 'limit'; // all trades are still limit trades let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -455,12 +479,6 @@ module.exports = class yobit extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, 'taker'); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': order, @@ -522,8 +540,8 @@ module.exports = class yobit extends Exchange { id = this.safeString (response['return'], 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (response['return'], 'received', 0.0); + remaining = this.safeNumber (response['return'], 'remains', amount); } const timestamp = this.milliseconds (); return { @@ -573,21 +591,13 @@ module.exports = class yobit extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp_created'); const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const remaining = this.safeFloat (order, 'amount'); - const amount = this.safeFloat (order, 'start_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - cost = price * filled; - } - } + const remaining = this.safeNumber (order, 'amount'); + const amount = this.safeNumber (order, 'start_amount'); + const price = this.safeNumber (order, 'rate'); const fee = undefined; const type = 'limit'; const side = this.safeString (order, 'type'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -601,16 +611,15 @@ module.exports = class yobit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zaif.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zaif.js index 2c6454a05..a94f9dddb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zaif.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zaif.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -127,6 +128,27 @@ module.exports = class zaif extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetCurrencyPairsAll (params); + // + // [ + // { + // "aux_unit_point": 0, + // "item_japanese": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3", + // "aux_unit_step": 5.0, + // "description": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3\u30fb\u65e5\u672c\u5186\u306e\u53d6\u5f15\u3092\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059", + // "item_unit_min": 0.001, + // "event_number": 0, + // "currency_pair": "btc_jpy", + // "is_token": false, + // "aux_unit_min": 5.0, + // "aux_japanese": "\u65e5\u672c\u5186", + // "id": 1, + // "item_unit_step": 0.0001, + // "name": "BTC/JPY", + // "seq": 0, + // "title": "BTC/JPY" + // } + // ] + // const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -137,8 +159,8 @@ module.exports = class zaif extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': -Math.log10 (market['item_unit_step']), - 'price': market['aux_unit_point'], + 'amount': -Math.log10 (this.safeNumber (market, 'item_unit_step')), + 'price': this.safeInteger (market, 'aux_unit_point'), }; const fees = this.safeValue (this.options['fees'], symbol, this.fees['trading']); const taker = fees['taker']; @@ -156,11 +178,11 @@ module.exports = class zaif extends Exchange { 'maker': maker, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'item_unit_min'), + 'min': this.safeNumber (market, 'item_unit_min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'aux_unit_min'), + 'min': this.safeNumber (market, 'aux_unit_min'), 'max': undefined, }, 'cost': { @@ -192,7 +214,7 @@ module.exports = class zaif extends Exchange { }; if ('deposit' in balances) { if (currencyId in balances['deposit']) { - account['total'] = this.safeFloat (balances['deposit'], currencyId); + account['total'] = this.safeNumber (balances['deposit'], currencyId); account['used'] = account['total'] - account['free']; } } @@ -217,22 +239,22 @@ module.exports = class zaif extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.milliseconds (); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -253,14 +275,11 @@ module.exports = class zaif extends Exchange { side = (side === 'bid') ? 'buy' : 'sell'; const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString2 (trade, 'id', 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); return { @@ -338,16 +357,10 @@ module.exports = class zaif extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp'); const marketId = this.safeString (order, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -361,7 +374,7 @@ module.exports = class zaif extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': undefined, 'remaining': undefined, @@ -369,7 +382,7 @@ module.exports = class zaif extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zb.js b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zb.js index 1f8f61cdf..29bea651d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zb.js +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/zb.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadRequest, ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, OrderNotFound, ExchangeNotAvailable, DDoSProtection, InvalidOrder, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89,8 +90,8 @@ module.exports = class zb extends Exchange { 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg', 'api': { - 'public': 'http://api.zb.cn/data', // no https for public API - 'private': 'https://trade.zb.cn/api', + 'public': 'https://api.zb.today/data', + 'private': 'https://trade.zb.today/api', }, 'www': 'https://www.zb.com', 'doc': 'https://www.zb.com/i/developer', @@ -205,6 +206,16 @@ module.exports = class zb extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetMarkets (params); + // + // { + // "zb_qc":{ + // "amountScale":2, + // "minAmount":0.01, + // "minSize":5, + // "priceScale":4, + // }, + // } + // const keys = Object.keys (markets); const result = []; for (let i = 0; i < keys.length; i++) { @@ -268,11 +279,11 @@ module.exports = class zb extends Exchange { const account = this.account (); const currencyId = this.safeString (balance, 'key'); const code = this.safeCurrencyCode (currencyId); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'freez'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'freez'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -321,18 +332,6 @@ module.exports = class zb extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetGetPayinAddress (params); @@ -439,16 +438,16 @@ module.exports = class zb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -458,12 +457,23 @@ module.exports = class zb extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; } + parseOHLCV (ohlcv, market = undefined) { + return [ + this.safeInteger (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + ]; + } + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -488,14 +498,12 @@ module.exports = class zb extends Exchange { let side = this.safeString (trade, 'trade_type'); side = (side === 'bid') ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const costString = Precise.stringMul (priceString, amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (costString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -674,23 +682,13 @@ module.exports = class zb extends Exchange { const timestamp = this.safeInteger (order, 'trade_date'); const marketId = this.safeString (order, 'currency'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'trade_amount'); - const amount = this.safeFloat (order, 'total_amount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'trade_money'); - let average = undefined; + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'trade_amount'); + const amount = this.safeNumber (order, 'total_amount'); + const cost = this.safeNumber (order, 'trade_money'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((cost !== undefined) && (filled !== undefined) && (filled > 0)) { - average = cost / filled; - } const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fees'); + const feeCost = this.safeNumber (order, 'fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -705,7 +703,7 @@ module.exports = class zb extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -719,15 +717,15 @@ module.exports = class zb extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -790,7 +788,7 @@ module.exports = class zb extends Exchange { // const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'hash'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let timestamp = this.parse8601 (this.safeString (transaction, 'submit_time')); timestamp = this.safeInteger (transaction, 'submitTime', timestamp); let address = this.safeString2 (transaction, 'toAddress', 'address'); @@ -810,7 +808,7 @@ module.exports = class zb extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -843,7 +841,7 @@ module.exports = class zb extends Exchange { if (password === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires exchange.password or a safePwd parameter'); } - const fees = this.safeFloat (params, 'fees'); + const fees = this.safeNumber (params, 'fees'); if (fees === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires a fees parameter'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/package.json b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/package.json index a5305f19f..8e0bd3de4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/package.json +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/package.json @@ -1,27 +1,27 @@ { - "_from": "ccxt@1.42.77", - "_id": "ccxt@1.42.77", + "_from": "ccxt@1.47.49", + "_id": "ccxt@1.47.49", "_inBundle": false, - "_integrity": "sha512-vPaw8G3hr9iq1iJ59EHuA6iqjufgK6dNC7MjT3qV8YQbpEJoD2ynoFwfl1hbuvlyKlFjiOa3gHwhRV64UacBDQ==", + "_integrity": "sha512-aGjOGKX/wfStwD24dH7FweP2ktdbZBjhgLxkipFVaewnjsftyiuzCCikMS7IvSRON/aAMG0oqKUdVHL382BFMA==", "_location": "/ccxt", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "ccxt@1.42.77", + "raw": "ccxt@1.47.49", "name": "ccxt", "escapedName": "ccxt", - "rawSpec": "1.42.77", + "rawSpec": "1.47.49", "saveSpec": null, - "fetchSpec": "1.42.77" + "fetchSpec": "1.47.49" }, "_requiredBy": [ "#USER", "/" ], - "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.42.77.tgz", - "_shasum": "8ab5f8e7190854e163da6d4fcf44530794d0a21c", - "_spec": "ccxt@1.42.77", + "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.47.49.tgz", + "_shasum": "ef9c41b5573b85d3b83cf1292d0aa891c4d5b6bc", + "_spec": "ccxt@1.47.49", "_where": "C:\\Superalgos\\Projects\\Superalgos\\TS\\Bot-Modules\\Sensor-Bot\\Exchange-Raw-Data", "author": { "name": "Igor Kroitor", @@ -543,7 +543,9 @@ "equos.io", "EQUOS", "ndax.io", - "NDAX" + "NDAX", + "ascendex.com", + "AscendEX" ], "license": "MIT", "main": "./ccxt.js", @@ -587,5 +589,5 @@ }, "types": "./ccxt.d.ts", "unpkg": "dist/ccxt.browser.js", - "version": "1.42.77" + "version": "1.47.49" } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/package-lock.json b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/package-lock.json index 976144cc2..cd3bb8d9e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/package-lock.json +++ b/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/package-lock.json @@ -3,9 +3,9 @@ "lockfileVersion": 1, "dependencies": { "ccxt": { - "version": "1.42.77", - "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.42.77.tgz", - "integrity": "sha512-vPaw8G3hr9iq1iJ59EHuA6iqjufgK6dNC7MjT3qV8YQbpEJoD2ynoFwfl1hbuvlyKlFjiOa3gHwhRV64UacBDQ==" + "version": "1.47.49", + "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.47.49.tgz", + "integrity": "sha512-aGjOGKX/wfStwD24dH7FweP2ktdbZBjhgLxkipFVaewnjsftyiuzCCikMS7IvSRON/aAMG0oqKUdVHL382BFMA==" } } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/CONTRIBUTING.md b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/CONTRIBUTING.md index 1d3ff05d1..7ff3d7ae6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/CONTRIBUTING.md +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/CONTRIBUTING.md @@ -261,7 +261,7 @@ These files containing derived exchange classes are transpiled from JS into PHP: These PHP base classes and files are not transpiled: -- `php/base/*` +- `php/Exchange.php php/ExchangeError.php php/Precise.php ... #### Typescript @@ -385,7 +385,7 @@ async fetchTicker (symbol, params = {}) { #### Parsing Symbols -When sending requests to the exchange unified symbols have to be _"converted"_ to exchange-specific market-`id`s like shown above. The same is true on the other side – when receiving an exchange response it has an exchange-specific market-`id` inside it that has to be _"converted back"_ to a unified CCXT symbol. +When sending requests to the exchange unified symbols have to be _"converted"_ to exchange-specific market-`id`s like shown above. The same is true on the other end – when receiving an exchange response it has an exchange-specific market-`id` inside it that has to be _"converted back"_ to a unified CCXT symbol. **We don't put exchange-specific market-`id`s in unified structures directly!** We can't freely interchange symbols with ids! There is a significant difference between an *exchange-specific market-ids* and *unified symbols*! This is explained in the Manual, here: @@ -444,7 +444,7 @@ In JavaScript, dictionary keys can be accessed in two notations: Both work almost identically, and one is implicitly converted to another upon executing the JavaScript code. -While the above does work in JavaScript, it will not work in Python or PHP. In most languages, associative dictionary keys are not treated in the same way as properties. Therefore, in Python `object.key` is not the same as `object['key']`. In PHP `$object->key` is not the same as `$object['key']` as well. Languages that differentiate between associative keys and properties use different notations for the two. +While the above does work in JavaScript, **it will not work in Python or PHP**. In most languages, associative dictionary keys are not treated in the same way as properties. Therefore, in Python `object.key` is not the same as `object['key']`. In PHP `$object->key` is not the same as `$object['key']` as well. Languages that differentiate between associative keys and properties use different notations for the two. To keep the code transpileable, please, remember this simple rule: *always use the single-quoted string key notation `object['key']` for accessing all associative dictionary keys in all languages everywhere throughout this library!* @@ -572,7 +572,7 @@ The `hmac()` method also supports `'base64'` for the `digest` argument. This is #### Timestamps -**All timestamps throughout all unified structures within this library are integer timestamp _in milliseconds_!** +**All timestamps throughout all unified structures within this library are integer UTC timestamps _in milliseconds_!** In order to convert to milliseconds timestamps, CCXT implements the following methods: diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/README.md b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/README.md index 3f8dfeea4..7ec80167e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/README.md +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/README.md @@ -1,6 +1,6 @@ # CCXT – CryptoCurrency eXchange Trading Library -[![Build Status](https://travis-ci.com/ccxt/ccxt.svg?branch=master)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/dhzSKYU) [![Supported Exchanges](https://img.shields.io/badge/exchanges-126-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Open Collective](https://opencollective.com/ccxt/backers/badge.svg)](https://opencollective.com/ccxt) +[![Build Status](https://travis-ci.com/ccxt/ccxt.svg?branch=master)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/dhzSKYU) [![Supported Exchanges](https://img.shields.io/badge/exchanges-121-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Open Collective](https://opencollective.com/ccxt/backers/badge.svg)](https://opencollective.com/ccxt) [![Twitter Follow](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://twitter.com/ccxt_official) A JavaScript / Python / PHP library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs. @@ -25,10 +25,10 @@ Current feature list: ## See Also -- [![Quadency](https://user-images.githubusercontent.com/1294454/69334382-a0618100-0c6b-11ea-9ba9-40aa97440cfa.png)](https://quadency.com?utm_source=ccxt)  **[Quadency](https://quadency.com?utm_source=ccxt)** — trading automation terminal for leading exchanges with streaming APIs + Python IDE. - [![TabTrader](https://user-images.githubusercontent.com/1294454/66755907-9c3e8880-eea1-11e9-846e-0bff349ceb87.png)](https://tab-trader.com/?utm_source=ccxt)  **[TabTrader](https://tab-trader.com/?utm_source=ccxt)** — trading on all exchanges in one app. Avaliable on [Android](https://play.google.com/store/apps/details?id=com.tabtrader.android&referrer=utm_source%3Dccxt) and [iOS](https://itunes.apple.com/app/apple-store/id1095716562?mt=8). - [![Pionex](https://user-images.githubusercontent.com/1294454/106112806-c2ec0580-615e-11eb-870c-0b7aef021db2.png)](https://www.pionex.com/en-US/sign?r=8wSFCbNk&utm_source=ad&utm_medium=banner&utm_campaign=ccxt-2)  **[Pionex](https://www.pionex.com/en-US/sign?r=8wSFCbNk&utm_source=ad&utm_medium=banner&utm_campaign=ccxt-2)** — 6 grid bots, spot-futures arb bot, smart trade and DCA bots. Free for [Android](https://play.google.com/store/apps/details?id=com.pionex.client&referrer=utm_source%3Dccxt) and [iOS](https://apps.apple.com/us/app/pionex/id1485348891?pt=ccxt&ct=inline)! - [![AAX](https://user-images.githubusercontent.com/1294454/106509642-ef957980-64de-11eb-92e0-8323cda7874e.png)](https://www.aaxpro.com/en-US/ad-sign-up/?utm_source=ccxt&utm_medium=one-liner&utm_campaign=futures)  **[AAX](https://www.aaxpro.com/en-US/ad-sign-up/?utm_source=ccxt&utm_medium=one-liner&utm_campaign=futures)** — trade bitcoin futures with fees as low as 0.02% and up to 100x leverage! +- [![Freqtrade](https://user-images.githubusercontent.com/1294454/114340585-8e35fa80-9b60-11eb-860f-4379125e2db6.png)](https://www.freqtrade.io)  **[Freqtrade](https://www.freqtrade.io)** — leading opensource cryptocurrency algorithmic trading software! ## Certified Cryptocurrency Exchanges @@ -52,13 +52,13 @@ Current feature list: ## Supported Cryptocurrency Exchange Markets -The CCXT library currently supports the following 126 cryptocurrency exchange markets and trading APIs: +The CCXT library currently supports the following 121 cryptocurrency exchange markets and trading APIs: | logo | id | name | ver | doc | certified | pro | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|-----------------------------------------------------------------------------------------|:---:|:-------------------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------| | [![aax](https://user-images.githubusercontent.com/1294454/104140087-a27f2580-53c0-11eb-87c1-5d9e81208fe9.jpg)](https://www.aaxpro.com/invite/sign-up?inviteCode=JXGm5Fy7R2MB) | aax | [AAX](https://www.aaxpro.com/invite/sign-up?inviteCode=JXGm5Fy7R2MB) | 2 | [API](https://www.aaxpro.com/apidoc/index.html) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | -| [![acx](https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg)](https://acx.io) | acx | [ACX](https://acx.io) | 2 | [API](https://acx.io/documents/api_v2) | | | | [![aofex](https://user-images.githubusercontent.com/51840849/77670271-056d1080-6f97-11ea-9ac2-4268e9ed0c1f.jpg)](https://aofex.com/#/register?key=9763840) | aofex | [AOFEX](https://aofex.com/#/register?key=9763840) | * | [API](https://aofex.zendesk.com/hc/en-us/sections/360005576574-API) | | | +| [![ascendex](https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg)](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | ascendex | [AscendEX](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | 1 | [API](https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation) | | | | [![bequant](https://user-images.githubusercontent.com/1294454/55248342-a75dfe00-525a-11e9-8aa2-05e9dca943c6.jpg)](https://bequant.io) | bequant | [Bequant](https://bequant.io) | 2 | [API](https://api.bequant.io/) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bibox](https://user-images.githubusercontent.com/51840849/77257418-3262b000-6c85-11ea-8fb8-20bdf20b3592.jpg)](https://w2.bibox365.com/login/register?invite_code=05Kj3I) | bibox | [Bibox](https://w2.bibox365.com/login/register?invite_code=05Kj3I) | 1 | [API](https://biboxcom.github.io/en/) | | | | [![bigone](https://user-images.githubusercontent.com/1294454/69354403-1d532180-0c91-11ea-88ed-44c06cefdf87.jpg)](https://b1.run/users/new?code=D3LLBVFT) | bigone | [BigONE](https://b1.run/users/new?code=D3LLBVFT) | 3 | [API](https://open.big.one/docs/api.html) | | | @@ -76,7 +76,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bithumb](https://user-images.githubusercontent.com/1294454/30597177-ea800172-9d5e-11e7-804c-b9d4fa9b56b0.jpg)](https://www.bithumb.com) | bithumb | [Bithumb](https://www.bithumb.com) | * | [API](https://apidocs.bithumb.com) | | | | [![bitkk](https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg)](https://www.bitkk.com) | bitkk | [bitkk](https://www.bitkk.com) | 1 | [API](https://www.bitkk.com/i/developer) | | | | [![bitmart](https://user-images.githubusercontent.com/1294454/61835713-a2662f80-ae85-11e9-9d00-6442919701fd.jpg)](http://www.bitmart.com/?r=rQCFLh) | bitmart | [BitMart](http://www.bitmart.com/?r=rQCFLh) | 1 | [API](https://developer-pro.bitmart.com/) | | | -| [![bitmax](https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg)](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | bitmax | [BitMax](https://bitmax.io/#/register?inviteCode=EL6BXBQM) | 1 | [API](https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation) | | | | [![bitmex](https://user-images.githubusercontent.com/1294454/27766319-f653c6e6-5ed4-11e7-933d-f0bc3699ae8f.jpg)](https://www.bitmex.com/register/upZpOX) | bitmex | [BitMEX](https://www.bitmex.com/register/upZpOX) | 1 | [API](https://www.bitmex.com/app/apiOverview) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bitpanda](https://user-images.githubusercontent.com/51840849/87591171-9a377d80-c6f0-11ea-94ac-97a126eac3bc.jpg)](https://www.bitpanda.com/en/pro) | bitpanda | [Bitpanda Pro](https://www.bitpanda.com/en/pro) | 1 | [API](https://developers.bitpanda.com/exchange/) | | | | [![bitso](https://user-images.githubusercontent.com/51840849/87295554-11f98280-c50e-11ea-80d6-15b3bafa8cbf.jpg)](https://bitso.com/?ref=itej) | bitso | [Bitso](https://bitso.com/?ref=itej) | 3 | [API](https://bitso.com/api_info) | | | @@ -84,7 +83,7 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bitstamp1](https://user-images.githubusercontent.com/1294454/27786377-8c8ab57e-5fe9-11e7-8ea4-2b05b6bcceec.jpg)](https://www.bitstamp.net) | bitstamp1 | [Bitstamp](https://www.bitstamp.net) | 1 | [API](https://www.bitstamp.net/api) | | | | [![bittrex](https://user-images.githubusercontent.com/51840849/87153921-edf53180-c2c0-11ea-96b9-f2a9a95a455b.jpg)](https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B) | bittrex | [Bittrex](https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B) | 3 | [API](https://bittrex.github.io/api/v3) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![bitvavo](https://user-images.githubusercontent.com/1294454/83165440-2f1cf200-a116-11ea-9046-a255d09fb2ed.jpg)](https://bitvavo.com/?a=24F34952F7) | bitvavo | [Bitvavo](https://bitvavo.com/?a=24F34952F7) | 2 | [API](https://docs.bitvavo.com/) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![bitz](https://user-images.githubusercontent.com/51840849/87443304-fec5e000-c5fd-11ea-98f8-ba8e67f7eaff.jpg)](https://u.bitz.com/register?invite_code=1429193) | bitz | [Bit-Z](https://u.bitz.com/register?invite_code=1429193) | 2 | [API](https://apidoc.bitz.com/en/) | | | +| [![bitz](https://user-images.githubusercontent.com/51840849/87443304-fec5e000-c5fd-11ea-98f8-ba8e67f7eaff.jpg)](https://u.bitz.com/register?invite_code=1429193) | bitz | [Bit-Z](https://u.bitz.com/register?invite_code=1429193) | 2 | [API](https://apidocv2.bitz.plus/en/) | | | | [![bl3p](https://user-images.githubusercontent.com/1294454/28501752-60c21b82-6feb-11e7-818b-055ee6d0e754.jpg)](https://bl3p.eu) | bl3p | [BL3P](https://bl3p.eu) | 1 | [API](https://github.com/BitonicNL/bl3p-api/tree/master/docs) | | | | [![bleutrade](https://user-images.githubusercontent.com/1294454/30303000-b602dbe6-976d-11e7-956d-36c5049c01e7.jpg)](https://bleutrade.com) | bleutrade | [Bleutrade](https://bleutrade.com) | * | [API](https://app.swaggerhub.com/apis-docs/bleu/white-label/3.0.0) | | | | [![braziliex](https://user-images.githubusercontent.com/1294454/34703593-c4498674-f504-11e7-8d14-ff8e44fb78c1.jpg)](https://braziliex.com/?ref=5FE61AB6F6D67DA885BC98BA27223465) | braziliex | [Braziliex](https://braziliex.com/?ref=5FE61AB6F6D67DA885BC98BA27223465) | * | [API](https://braziliex.com/exchange/api.php) | | | @@ -99,7 +98,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![bytetrade](https://user-images.githubusercontent.com/1294454/67288762-2f04a600-f4e6-11e9-9fd6-c60641919491.jpg)](https://www.byte-trade.com) | bytetrade | [ByteTrade](https://www.byte-trade.com) | * | [API](https://docs.byte-trade.com/#description) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | | [![cdax](https://user-images.githubusercontent.com/1294454/102157692-fd406280-3e90-11eb-8d46-4511b617cd17.jpg)](https://cdax.io/invite?invite_code=esc74) | cdax | [CDAX](https://cdax.io/invite?invite_code=esc74) | 1 | [API](https://github.com/cloudapidoc/API_Docs) | | | | [![cex](https://user-images.githubusercontent.com/1294454/27766442-8ddc33b0-5ed8-11e7-8b98-f786aef0f3c9.jpg)](https://cex.io/r/0/up105393824/0/) | cex | [CEX.IO](https://cex.io/r/0/up105393824/0/) | * | [API](https://cex.io/cex-api) | | | -| [![chilebit](https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg)](https://chilebit.net) | chilebit | [ChileBit](https://chilebit.net) | 1 | [API](https://blinktrade.com/docs) | | | | [![coinbase](https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg)](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | coinbase | [Coinbase](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | 2 | [API](https://developers.coinbase.com/api/v2) | | | | [![coinbaseprime](https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg)](https://prime.coinbase.com) | coinbaseprime | [Coinbase Prime](https://prime.coinbase.com) | * | [API](https://docs.prime.coinbase.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![coinbasepro](https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg)](https://pro.coinbase.com/) | coinbasepro | [Coinbase Pro](https://pro.coinbase.com/) | * | [API](https://docs.pro.coinbase.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | @@ -118,7 +116,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![delta](https://user-images.githubusercontent.com/1294454/99450025-3be60a00-2931-11eb-9302-f4fd8d8589aa.jpg)](https://www.delta.exchange/app/signup/?code=IULYNB) | delta | [Delta Exchange](https://www.delta.exchange/app/signup/?code=IULYNB) | 2 | [API](https://docs.delta.exchange) | | | | [![deribit](https://user-images.githubusercontent.com/1294454/41933112-9e2dd65a-798b-11e8-8440-5bab2959fcb8.jpg)](https://www.deribit.com/reg-1189.4038) | deribit | [Deribit](https://www.deribit.com/reg-1189.4038) | 2 | [API](https://docs.deribit.com/v2) | | | | [![digifinex](https://user-images.githubusercontent.com/51840849/87443315-01283a00-c5fe-11ea-8628-c2a0feaf07ac.jpg)](https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp) | digifinex | [DigiFinex](https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp) | 3 | [API](https://docs.digifinex.com) | | | -| [![dsx](https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg)](https://dsxglobal.com) | dsx | [DSX](https://dsxglobal.com) | 3 | [API](https://dsxglobal.com/developers/publicApi) | | | | [![equos](https://user-images.githubusercontent.com/1294454/107758499-05edd180-6d38-11eb-9e09-0b69602a7a15.jpg)](https://equos.io?referredByCode=zpa8kij4ouvBFup3) | equos | [EQUOS](https://equos.io?referredByCode=zpa8kij4ouvBFup3) | * | [API](https://developer.equos.io) | | | | [![eterbase](https://user-images.githubusercontent.com/1294454/82067900-faeb0f80-96d9-11ea-9f22-0071cfcb9871.jpg)](https://eterbase.exchange/invite/1wjjh4Pe) | eterbase | [Eterbase](https://eterbase.exchange/invite/1wjjh4Pe) | 1 | [API](https://developers.eterbase.exchange) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | | [![exmo](https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg)](https://exmo.me/?ref=131685) | exmo | [EXMO](https://exmo.me/?ref=131685) | 1.1 | [API](https://exmo.me/en/api_doc?ref=131685) | | | @@ -133,10 +130,9 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![gopax](https://user-images.githubusercontent.com/1294454/102897212-ae8a5e00-4478-11eb-9bab-91507c643900.jpg)](https://www.gopax.co.kr) | gopax | [GOPAX](https://www.gopax.co.kr) | 1 | [API](https://gopax.github.io/API/index.en.html) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![hbtc](https://user-images.githubusercontent.com/51840849/80134449-70663300-85a7-11ea-8942-e204cdeaab5d.jpg)](https://www.hbtc.com/register/O2S8NS) | hbtc | [HBTC](https://www.hbtc.com/register/O2S8NS) | 1 | [API](https://github.com/bhexopen/BHEX-OpenApi/tree/master/doc) | | | | [![hitbtc](https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg)](https://hitbtc.com/?ref_id=5a5d39a65d466) | hitbtc | [HitBTC](https://hitbtc.com/?ref_id=5a5d39a65d466) | 2 | [API](https://api.hitbtc.com) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![hollaex](https://user-images.githubusercontent.com/1294454/75841031-ca375180-5ddd-11ea-8417-b975674c23cb.jpg)](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | hollaex | [HollaEx](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | 1 | [API](https://apidocs.hollaex.com) | | | +| [![hollaex](https://user-images.githubusercontent.com/1294454/75841031-ca375180-5ddd-11ea-8417-b975674c23cb.jpg)](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | hollaex | [HollaEx](https://pro.hollaex.com/signup?affiliation_code=QSWA6G) | 2 | [API](https://apidocs.hollaex.com) | | | | [![huobijp](https://user-images.githubusercontent.com/1294454/85734211-85755480-b705-11ea-8b35-0b7f1db33a2f.jpg)](https://www.huobi.co.jp/register/?invite_code=znnq3) | huobijp | [Huobi Japan](https://www.huobi.co.jp/register/?invite_code=znnq3) | 1 | [API](https://api-doc.huobi.co.jp) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![huobipro](https://user-images.githubusercontent.com/1294454/76137448-22748a80-604e-11ea-8069-6e389271911d.jpg)](https://www.huobi.com/en-us/topic/invited/?invite_code=rwrd3) | huobipro | [Huobi Pro](https://www.huobi.com/en-us/topic/invited/?invite_code=rwrd3) | 1 | [API](https://huobiapi.github.io/docs/spot/v1/cn/) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![ice3x](https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg)](https://ice3x.com?ref=14341802) | ice3x | [ICE3X](https://ice3x.com?ref=14341802) | 1 | [API](https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017) | | | | [![idex](https://user-images.githubusercontent.com/51840849/94481303-2f222100-01e0-11eb-97dd-bc14c5943a86.jpg)](https://idex.io) | idex | [IDEX](https://idex.io) | 2 | [API](https://docs.idex.io/) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | | [![independentreserve](https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg)](https://www.independentreserve.com) | independentreserve | [Independent Reserve](https://www.independentreserve.com) | * | [API](https://www.independentreserve.com/API) | | | | [![indodax](https://user-images.githubusercontent.com/51840849/87070508-9358c880-c221-11ea-8dc5-5391afbbb422.jpg)](https://indodax.com/ref/testbitcoincoid/1) | indodax | [INDODAX](https://indodax.com/ref/testbitcoincoid/1) | 2.0 | [API](https://github.com/btcid/indodax-official-api-docs) | | | @@ -172,7 +168,6 @@ The CCXT library currently supports the following 126 cryptocurrency exchange ma | [![tidex](https://user-images.githubusercontent.com/1294454/30781780-03149dc4-a12e-11e7-82bb-313b269d24d4.jpg)](https://tidex.com/exchange/?ref=57f5638d9cd7) | tidex | [Tidex](https://tidex.com/exchange/?ref=57f5638d9cd7) | 3 | [API](https://tidex.com/exchange/public-api) | | | | [![timex](https://user-images.githubusercontent.com/1294454/70423869-6839ab00-1a7f-11ea-8f94-13ae72c31115.jpg)](https://timex.io/?refcode=1x27vNkTbP1uwkCck) | timex | [TimeX](https://timex.io/?refcode=1x27vNkTbP1uwkCck) | 1 | [API](https://docs.timex.io) | | | | [![upbit](https://user-images.githubusercontent.com/1294454/49245610-eeaabe00-f423-11e8-9cba-4b0aed794799.jpg)](https://upbit.com) | upbit | [Upbit](https://upbit.com) | 1 | [API](https://docs.upbit.com/docs/%EC%9A%94%EC%B2%AD-%EC%88%98-%EC%A0%9C%ED%95%9C) | | [![CCXT Pro](https://img.shields.io/badge/CCXT-Pro-black)](https://ccxt.pro) | -| [![vaultoro](https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg)](https://www.vaultoro.com) | vaultoro | [Vaultoro](https://www.vaultoro.com) | 1 | [API](https://api.vaultoro.com) | | | | [![vbtc](https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg)](https://vbtc.exchange) | vbtc | [VBTC](https://vbtc.exchange) | 1 | [API](https://blinktrade.com/docs) | | | | [![vcc](https://user-images.githubusercontent.com/1294454/100545356-8427f500-326c-11eb-9539-7d338242d61b.jpg)](https://vcc.exchange?ref=l4xhrH) | vcc | [VCC Exchange](https://vcc.exchange?ref=l4xhrH) | 3 | [API](https://vcc.exchange/api) | | | | [![wavesexchange](https://user-images.githubusercontent.com/1294454/84547058-5fb27d80-ad0b-11ea-8711-78ac8b3c7f31.jpg)](https://waves.exchange) | wavesexchange | [Waves.Exchange](https://waves.exchange) | * | [API](https://docs.waves.exchange) | [![CCXT Certified](https://img.shields.io/badge/CCXT-Certified-green.svg)](https://github.com/ccxt/ccxt/wiki/Certification) | | @@ -229,13 +224,13 @@ console.log (ccxt.exchanges) // print all available exchanges All-in-one browser bundle (dependencies included), served from a CDN of your choice: -* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@1.42.77/dist/ccxt.browser.js -* unpkg: https://unpkg.com/ccxt@1.42.77/dist/ccxt.browser.js +* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@1.47.49/dist/ccxt.browser.js +* unpkg: https://unpkg.com/ccxt@1.47.49/dist/ccxt.browser.js CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers. ```HTML - + ``` Creates a global `ccxt` object: diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/export-exchanges.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/export-exchanges.js index 580d2cb2c..24ee4806f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/export-exchanges.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/export-exchanges.js @@ -195,7 +195,6 @@ function createMarkdownTable (array, markdownMethod, centeredColumns) { // const columns = underline.split ('|') - for (const i of centeredColumns) { columns[i] = ':' + columns[i].slice (1, columns[i].length - 1) + ':' } @@ -219,51 +218,45 @@ function exportSupportedAndCertifiedExchanges (exchanges, { allExchangesPaths, c const exchangesNotListedInDocs = [ 'hitbtc2' ] const arrayOfExchanges = values (exchanges) + const numExchanges = arrayOfExchanges.length - if (allExchangesPaths) { - + if (allExchangesPaths && numExchanges) { const supportedExchangesMarkdownTable = createMarkdownTable (arrayOfExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , numExchanges = arrayOfExchanges.length , beginning = "The CCXT library currently supports the following " , ending = " cryptocurrency exchange markets and trading APIs:\n\n" , totalString = beginning + numExchanges + ending , allExchangesReplacement = totalString + supportedExchangesMarkdownTable + "$1" , allExchangesRegex = new RegExp ("[^\n]+[\n]{2}\\| logo[^`]+\\|([\n][\n]|[\n]$|$)", 'm') - for (const path of allExchangesPaths) { logExportExchanges (path, allExchangesRegex, allExchangesReplacement) } } - if (proExchangesPaths) { - - const proExchanges = arrayOfExchanges.filter (exchange => exchange.pro) - , proExchangesMarkdownTable = createMarkdownTable (proExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , numExchanges = proExchanges.length + const proExchanges = arrayOfExchanges.filter (exchange => exchange.pro) + const numProExchanges = proExchanges.length + if (proExchangesPaths && numProExchanges) { + const proExchangesMarkdownTable = createMarkdownTable (proExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) , beginning = "The CCXT Pro library currently supports the following " , ending = " cryptocurrency exchange markets and WebSocket trading APIs:\n\n" - , totalString = beginning + numExchanges + ending + , totalString = beginning + numProExchanges + ending , proExchangesReplacement = totalString + proExchangesMarkdownTable + "$1" , proExchangesRegex = new RegExp ("[^\n]+[\n]{2}\\|[^`]+\\|([\n][\n]|[\n]$|$)", 'm') - for (const path of proExchangesPaths) { logExportExchanges (path, proExchangesRegex, proExchangesReplacement) } } - if (certifiedExchangesPaths) { - const certifiedExchanges = arrayOfExchanges.filter (exchange => exchange.certified) - , certifiedExchangesMarkdownTable = createMarkdownTable (certifiedExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) - , certifiedExchangesReplacement = '$1' + certifiedExchangesMarkdownTable + "\n" - , certifiedExchangesRegex = new RegExp ("^(## Certified Cryptocurrency Exchanges\n{3})(?:\\|.+\\|$\n)+", 'm') - + const certifiedExchanges = arrayOfExchanges.filter (exchange => exchange.certified) + if (certifiedExchangesPaths && certifiedExchanges.length) { + const certifiedExchangesMarkdownTable = createMarkdownTable (certifiedExchanges, createMarkdownListOfExchanges, [ 3, 4 ]) + , certifiedExchangesReplacement = '$1' + certifiedExchangesMarkdownTable + "\n" + , certifiedExchangesRegex = new RegExp ("^(## Certified Cryptocurrency Exchanges\n{3})(?:\\|.+\\|$\n)+", 'm') for (const path of certifiedExchangesPaths) { logExportExchanges (path, certifiedExchangesRegex, certifiedExchangesReplacement) } } if (exchangesByCountriesPaths) { - const exchangesByCountriesMarkdownTable = createMarkdownTable (arrayOfExchanges, createMarkdownListOfExchangesByCountries, [ 4, 5 ]) const result = "# Exchanges By Country\n\nThe ccxt library currently supports the following cryptocurrency exchange markets and trading APIs:\n\n" + exchangesByCountriesMarkdownTable + "\n\n" for (const path of exchangesByCountriesPaths) { @@ -385,7 +378,7 @@ function exportEverything () { replacement: "exchanges = [\n" + " '" + ids.join ("',\n '") + "'," + "\n]", }, { - file: './php/base/Exchange.php', + file: './php/Exchange.php', regex: /public static \$exchanges \= array\s*\([^\)]+\)/, replacement: "public static $exchanges = array(\n '" + ids.join ("',\n '") + "',\n )", }, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/transpile.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/transpile.js index 948a34c0f..233d15e6c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/transpile.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/build/transpile.js @@ -34,6 +34,7 @@ class Transpiler { [ /\.safeIntegerProduct2\s/g, '.safe_integer_product_2'], [ /\.safeTimestamp2\s/g, '.safe_timestamp_2'], [ /\.safeString2\s/g, '.safe_string_2'], + [ /\.safeNumber2\s/g, '.safe_number_2'], [ /\.safeStringLower2\s/g, '.safe_string_lower_2'], [ /\.safeStringUpper2\s/g, '.safe_string_upper_2'], [ /\.safeValue2\s/g, '.safe_value_2'], @@ -195,6 +196,10 @@ class Transpiler { [ /Number\.MAX_SAFE_INTEGER/g, 'float(\'inf\')'], [ /function\s*(\w+\s*\([^)]+\))\s*{/g, 'def $1:'], [ /assert\s*\((.+)\);/g, 'assert $1'], + [ /Precise\.stringAdd\s/g, 'Precise.string_add' ], + [ /Precise\.stringMul\s/g, 'Precise.string_mul' ], + [ /Precise\.stringDiv\s/g, 'Precise.string_div' ], + [ /Precise\.stringSub\s/g, 'Precise.string_sub' ], // insert common regexes in the middle (critical) ].concat (this.getCommonRegexes ()).concat ([ @@ -227,7 +232,7 @@ class Transpiler { [ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(?:\<=|\>=|<|>)\s*(.*)\s*\;[^\)]+\)\s*{/g, 'for $1 in range($2, $3):'], [ /\s\|\|\s/g, ' or ' ], [ /\s\&\&\s/g, ' and ' ], - [ /\!([^\='"])/g, 'not $1'], + [ /\!([^\s\='"])/g, 'not $1'], [ /\.push\s*\(([\s\S]+?)\);/g, '.append($1);' ], [ /^(\s*}\s*$)+/gm, '' ], [ /\;(\s+?\/\/.+?)/g, '$1' ], @@ -243,9 +248,6 @@ class Transpiler { [ /parseFloat\s*/g, 'float'], [ /parseInt\s*/g, 'int'], [ /self\[([^\]+]+)\]/g, 'getattr(self, $1)' ], - [ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], - [ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], - [ /([^\s(:]+)\.length/g, 'len($1)' ], [ /Math\.floor\s*\(([^\)]+)\)/g, 'int(math.floor($1))' ], [ /Math\.abs\s*\(([^\)]+)\)/g, 'abs($1)' ], [ /Math\.pow\s*\(([^\)]+)\)/g, 'math.pow($1)' ], @@ -253,6 +255,9 @@ class Transpiler { [ /Math\.ceil\s*\(([^\)]+)\)/g, 'int(math.ceil($1))' ], [ /Math\.log/g, 'math.log' ], [ /([a-zA-Z0-9_\.]*\([^\)]+\)|[^\s]+)\s+\?\s*([^\:]+)\s+\:\s*([^\n]+)/g, '$2 if $1 else $3'], + [ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], + [ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], + [ /([^\s(:]+)\.length/g, 'len($1)' ], [ /(^|\s)\/\//g, '$1#' ], [ /([^\n\s]) #/g, '$1 #' ], // PEP8 E261 [ /\.indexOf/g, '.find'], @@ -336,6 +341,10 @@ class Transpiler { [ /(\w+)\.shift\s*\(\)/g, 'array_shift($1)' ], [ /(\w+)\.pop\s*\(\)/g, 'array_pop($1)' ], [ /Number\.MAX_SAFE_INTEGER/g, 'PHP_INT_MAX' ], + [ /Precise\.stringAdd\s/g, 'Precise::string_add' ], + [ /Precise\.stringDiv\s/g, 'Precise::string_div' ], + [ /Precise\.stringMul\s/g, 'Precise::string_mul' ], + [ /Precise\.stringSub\s/g, 'Precise::string_sub' ], // insert common regexes in the middle (critical) ].concat (this.getCommonRegexes ()).concat ([ @@ -404,6 +413,7 @@ class Transpiler { [ /([^\(\s]+)\s+%\s+([^\s\,\;\)]+)/g, 'fmod($1, $2)' ], [ /\(([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0\)/g, '(mb_strpos($1, $2) !== false)' ], [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0/g, 'mb_strpos($1, $2) !== false' ], + [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)\s*\<\s*0/g, 'mb_strpos($1, $2) === false' ], [ /([^\s\(]+)\.indexOf\s*\(([^\)]+)\)/g, 'mb_strpos($1, $2)' ], [ /\(([^\s\(]+)\sin\s([^\)]+)\)/g, '(is_array($2) && array_key_exists($1, $2))' ], [ /([^\s]+)\.join\s*\(\s*([^\)]+?)\s*\)/g, 'implode($2, $1)' ], @@ -578,6 +588,9 @@ class Transpiler { precisionImports.push ('from ccxt.base.decimal_to_precision import ' + constant) } } + if (bodyAsString.match (/[\s(]Precise/)) { + precisionImports.push ('from ccxt.base.precise import Precise') + } header = header.concat (libraries, errorImports, precisionImports) @@ -633,7 +646,13 @@ class Transpiler { } } - header = header.concat (errorImports) + const precisionImports = [] + + if (async && bodyAsString.match (/[\s(]Precise/)) { + precisionImports.push ('use \\ccxt\\Precise;') + } + + header = header.concat (errorImports).concat (precisionImports) methods = methods.concat (this.getPHPBaseMethods ()) @@ -1179,7 +1198,7 @@ class Transpiler { function phpMakeErrorClassFile (name, parent) { const useClause = "\nuse " + parent + ";\n" - const requireClause = "\nrequire_once PATH_TO_CCXT_BASE . '" + parent + ".php';\n" + const requireClause = "\nrequire_once PATH_TO_CCXT . '" + parent + ".php';\n" const phpBody = [ '; - createLimitOrder (symbol: string, side: Order['side'], amount: number, price?: number, params?: Params): Promise; + createLimitOrder (symbol: string, side: Order['side'], amount: number, price: number, params?: Params): Promise; + createLimitBuyOrder (symbol: string, amount: number, price: number, params?: Params): Promise; + createLimitSellOrder (symbol: string, amount: number, price: number, params?: Params): Promise; createMarketOrder (symbol: string, side: Order['side'], amount: number, price?: number, params?: Params): Promise; createOrder (symbol: string, type: Order['type'], side: Order['side'], amount: number, price?: number, params?: Params): Promise; decode (str: string): string; @@ -423,8 +425,8 @@ declare module 'ccxt' { /* tslint:disable */ export class aax extends Exchange {} - export class acx extends Exchange {} export class aofex extends Exchange {} + export class ascendex extends Exchange {} export class bequant extends hitbtc {} export class bibox extends Exchange {} export class bigone extends Exchange {} @@ -442,7 +444,6 @@ declare module 'ccxt' { export class bithumb extends Exchange {} export class bitkk extends zb {} export class bitmart extends Exchange {} - export class bitmax extends Exchange {} export class bitmex extends Exchange {} export class bitpanda extends Exchange {} export class bitso extends Exchange {} @@ -465,7 +466,6 @@ declare module 'ccxt' { export class bytetrade extends Exchange {} export class cdax extends huobipro {} export class cex extends Exchange {} - export class chilebit extends foxbit {} export class coinbase extends Exchange {} export class coinbaseprime extends coinbasepro {} export class coinbasepro extends Exchange {} @@ -484,7 +484,6 @@ declare module 'ccxt' { export class delta extends Exchange {} export class deribit extends Exchange {} export class digifinex extends Exchange {} - export class dsx extends Exchange {} export class equos extends Exchange {} export class eterbase extends Exchange {} export class exmo extends Exchange {} @@ -502,14 +501,13 @@ declare module 'ccxt' { export class hollaex extends Exchange {} export class huobijp extends huobipro {} export class huobipro extends Exchange {} - export class ice3x extends Exchange {} export class idex extends Exchange {} export class independentreserve extends Exchange {} export class indodax extends Exchange {} export class itbit extends Exchange {} export class kraken extends Exchange {} export class kucoin extends Exchange {} - export class kuna extends acx {} + export class kuna extends Exchange {} export class lakebtc extends Exchange {} export class latoken extends Exchange {} export class lbank extends Exchange {} @@ -538,7 +536,6 @@ declare module 'ccxt' { export class tidex extends Exchange {} export class timex extends Exchange {} export class upbit extends Exchange {} - export class vaultoro extends Exchange {} export class vbtc extends foxbit {} export class vcc extends Exchange {} export class wavesexchange extends Exchange {} @@ -553,8 +550,8 @@ declare module 'ccxt' { export type ExchangeId = | 'aax' - | 'acx' | 'aofex' + | 'ascendex' | 'bequant' | 'bibox' | 'bigone' @@ -572,7 +569,6 @@ declare module 'ccxt' { | 'bithumb' | 'bitkk' | 'bitmart' - | 'bitmax' | 'bitmex' | 'bitpanda' | 'bitso' @@ -595,7 +591,6 @@ declare module 'ccxt' { | 'bytetrade' | 'cdax' | 'cex' - | 'chilebit' | 'coinbase' | 'coinbaseprime' | 'coinbasepro' @@ -614,7 +609,6 @@ declare module 'ccxt' { | 'delta' | 'deribit' | 'digifinex' - | 'dsx' | 'equos' | 'eterbase' | 'exmo' @@ -632,7 +626,6 @@ declare module 'ccxt' { | 'hollaex' | 'huobijp' | 'huobipro' - | 'ice3x' | 'idex' | 'independentreserve' | 'indodax' @@ -668,7 +661,6 @@ declare module 'ccxt' { | 'tidex' | 'timex' | 'upbit' - | 'vaultoro' | 'vbtc' | 'vcc' | 'wavesexchange' diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/ccxt.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/ccxt.js index 1d5c72642..27dc35101 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/ccxt.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/ccxt.js @@ -35,7 +35,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.42.77' +const version = '1.47.49' Exchange.ccxtVersion = version @@ -43,8 +43,8 @@ Exchange.ccxtVersion = version const exchanges = { 'aax': require ('./js/aax.js'), - 'acx': require ('./js/acx.js'), 'aofex': require ('./js/aofex.js'), + 'ascendex': require ('./js/ascendex.js'), 'bequant': require ('./js/bequant.js'), 'bibox': require ('./js/bibox.js'), 'bigone': require ('./js/bigone.js'), @@ -62,7 +62,6 @@ const exchanges = { 'bithumb': require ('./js/bithumb.js'), 'bitkk': require ('./js/bitkk.js'), 'bitmart': require ('./js/bitmart.js'), - 'bitmax': require ('./js/bitmax.js'), 'bitmex': require ('./js/bitmex.js'), 'bitpanda': require ('./js/bitpanda.js'), 'bitso': require ('./js/bitso.js'), @@ -85,7 +84,6 @@ const exchanges = { 'bytetrade': require ('./js/bytetrade.js'), 'cdax': require ('./js/cdax.js'), 'cex': require ('./js/cex.js'), - 'chilebit': require ('./js/chilebit.js'), 'coinbase': require ('./js/coinbase.js'), 'coinbaseprime': require ('./js/coinbaseprime.js'), 'coinbasepro': require ('./js/coinbasepro.js'), @@ -104,7 +102,6 @@ const exchanges = { 'delta': require ('./js/delta.js'), 'deribit': require ('./js/deribit.js'), 'digifinex': require ('./js/digifinex.js'), - 'dsx': require ('./js/dsx.js'), 'equos': require ('./js/equos.js'), 'eterbase': require ('./js/eterbase.js'), 'exmo': require ('./js/exmo.js'), @@ -122,7 +119,6 @@ const exchanges = { 'hollaex': require ('./js/hollaex.js'), 'huobijp': require ('./js/huobijp.js'), 'huobipro': require ('./js/huobipro.js'), - 'ice3x': require ('./js/ice3x.js'), 'idex': require ('./js/idex.js'), 'independentreserve': require ('./js/independentreserve.js'), 'indodax': require ('./js/indodax.js'), @@ -158,7 +154,6 @@ const exchanges = { 'tidex': require ('./js/tidex.js'), 'timex': require ('./js/timex.js'), 'upbit': require ('./js/upbit.js'), - 'vaultoro': require ('./js/vaultoro.js'), 'vbtc': require ('./js/vbtc.js'), 'vcc': require ('./js/vcc.js'), 'wavesexchange': require ('./js/wavesexchange.js'), diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/dist/ccxt.browser.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/dist/ccxt.browser.js index e8b439fb1..334681baa 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/dist/ccxt.browser.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/dist/ccxt.browser.js @@ -43,7 +43,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.42.77' +const version = '1.47.49' Exchange.ccxtVersion = version @@ -51,8 +51,8 @@ Exchange.ccxtVersion = version const exchanges = { 'aax': require ('./js/aax.js'), - 'acx': require ('./js/acx.js'), 'aofex': require ('./js/aofex.js'), + 'ascendex': require ('./js/ascendex.js'), 'bequant': require ('./js/bequant.js'), 'bibox': require ('./js/bibox.js'), 'bigone': require ('./js/bigone.js'), @@ -70,7 +70,6 @@ const exchanges = { 'bithumb': require ('./js/bithumb.js'), 'bitkk': require ('./js/bitkk.js'), 'bitmart': require ('./js/bitmart.js'), - 'bitmax': require ('./js/bitmax.js'), 'bitmex': require ('./js/bitmex.js'), 'bitpanda': require ('./js/bitpanda.js'), 'bitso': require ('./js/bitso.js'), @@ -93,7 +92,6 @@ const exchanges = { 'bytetrade': require ('./js/bytetrade.js'), 'cdax': require ('./js/cdax.js'), 'cex': require ('./js/cex.js'), - 'chilebit': require ('./js/chilebit.js'), 'coinbase': require ('./js/coinbase.js'), 'coinbaseprime': require ('./js/coinbaseprime.js'), 'coinbasepro': require ('./js/coinbasepro.js'), @@ -112,7 +110,6 @@ const exchanges = { 'delta': require ('./js/delta.js'), 'deribit': require ('./js/deribit.js'), 'digifinex': require ('./js/digifinex.js'), - 'dsx': require ('./js/dsx.js'), 'equos': require ('./js/equos.js'), 'eterbase': require ('./js/eterbase.js'), 'exmo': require ('./js/exmo.js'), @@ -130,7 +127,6 @@ const exchanges = { 'hollaex': require ('./js/hollaex.js'), 'huobijp': require ('./js/huobijp.js'), 'huobipro': require ('./js/huobipro.js'), - 'ice3x': require ('./js/ice3x.js'), 'idex': require ('./js/idex.js'), 'independentreserve': require ('./js/independentreserve.js'), 'indodax': require ('./js/indodax.js'), @@ -166,7 +162,6 @@ const exchanges = { 'tidex': require ('./js/tidex.js'), 'timex': require ('./js/timex.js'), 'upbit': require ('./js/upbit.js'), - 'vaultoro': require ('./js/vaultoro.js'), 'vbtc': require ('./js/vbtc.js'), 'vcc': require ('./js/vcc.js'), 'wavesexchange': require ('./js/wavesexchange.js'), @@ -184,7 +179,7 @@ module.exports = Object.assign ({ version, Exchange, 'exchanges': Object.keys (e //----------------------------------------------------------------------------- -},{"./js/aax.js":3,"./js/acx.js":4,"./js/aofex.js":5,"./js/base/Exchange":6,"./js/base/errors":8,"./js/base/functions":9,"./js/bequant.js":20,"./js/bibox.js":21,"./js/bigone.js":22,"./js/binance.js":23,"./js/binanceus.js":24,"./js/bit2c.js":25,"./js/bitbank.js":26,"./js/bitbay.js":27,"./js/bitcoincom.js":28,"./js/bitfinex.js":29,"./js/bitfinex2.js":30,"./js/bitflyer.js":31,"./js/bitforex.js":32,"./js/bitget.js":33,"./js/bithumb.js":34,"./js/bitkk.js":35,"./js/bitmart.js":36,"./js/bitmax.js":37,"./js/bitmex.js":38,"./js/bitpanda.js":39,"./js/bitso.js":40,"./js/bitstamp.js":41,"./js/bitstamp1.js":42,"./js/bittrex.js":43,"./js/bitvavo.js":44,"./js/bitz.js":45,"./js/bl3p.js":46,"./js/bleutrade.js":47,"./js/braziliex.js":48,"./js/btcalpha.js":49,"./js/btcbox.js":50,"./js/btcmarkets.js":51,"./js/btctradeua.js":52,"./js/btcturk.js":53,"./js/buda.js":54,"./js/bw.js":55,"./js/bybit.js":56,"./js/bytetrade.js":57,"./js/cdax.js":58,"./js/cex.js":59,"./js/chilebit.js":60,"./js/coinbase.js":61,"./js/coinbaseprime.js":62,"./js/coinbasepro.js":63,"./js/coincheck.js":64,"./js/coinegg.js":65,"./js/coinex.js":66,"./js/coinfalcon.js":67,"./js/coinfloor.js":68,"./js/coingi.js":69,"./js/coinmarketcap.js":70,"./js/coinmate.js":71,"./js/coinone.js":72,"./js/coinspot.js":73,"./js/crex24.js":74,"./js/currencycom.js":75,"./js/delta.js":76,"./js/deribit.js":77,"./js/digifinex.js":78,"./js/dsx.js":79,"./js/equos.js":80,"./js/eterbase.js":81,"./js/exmo.js":82,"./js/exx.js":83,"./js/fcoin.js":84,"./js/fcoinjp.js":85,"./js/flowbtc.js":86,"./js/foxbit.js":87,"./js/ftx.js":88,"./js/gateio.js":89,"./js/gemini.js":90,"./js/gopax.js":91,"./js/hbtc.js":92,"./js/hitbtc.js":93,"./js/hollaex.js":94,"./js/huobijp.js":95,"./js/huobipro.js":96,"./js/ice3x.js":97,"./js/idex.js":98,"./js/independentreserve.js":99,"./js/indodax.js":100,"./js/itbit.js":101,"./js/kraken.js":102,"./js/kucoin.js":103,"./js/kuna.js":104,"./js/lakebtc.js":105,"./js/latoken.js":106,"./js/lbank.js":107,"./js/liquid.js":108,"./js/luno.js":109,"./js/lykke.js":110,"./js/mercado.js":111,"./js/mixcoins.js":112,"./js/ndax.js":113,"./js/novadax.js":114,"./js/oceanex.js":115,"./js/okcoin.js":116,"./js/okex.js":117,"./js/paymium.js":118,"./js/phemex.js":119,"./js/poloniex.js":120,"./js/probit.js":121,"./js/qtrade.js":122,"./js/rightbtc.js":123,"./js/ripio.js":124,"./js/southxchange.js":125,"./js/stex.js":166,"./js/surbitcoin.js":167,"./js/therock.js":168,"./js/tidebit.js":169,"./js/tidex.js":170,"./js/timex.js":171,"./js/upbit.js":172,"./js/vaultoro.js":173,"./js/vbtc.js":174,"./js/vcc.js":175,"./js/wavesexchange.js":176,"./js/whitebit.js":177,"./js/xbtce.js":178,"./js/xena.js":179,"./js/yobit.js":180,"./js/zaif.js":181,"./js/zb.js":182}],3:[function(require,module,exports){ +},{"./js/aax.js":3,"./js/aofex.js":4,"./js/ascendex.js":5,"./js/base/Exchange":6,"./js/base/errors":9,"./js/base/functions":10,"./js/bequant.js":21,"./js/bibox.js":22,"./js/bigone.js":23,"./js/binance.js":24,"./js/binanceus.js":25,"./js/bit2c.js":26,"./js/bitbank.js":27,"./js/bitbay.js":28,"./js/bitcoincom.js":29,"./js/bitfinex.js":30,"./js/bitfinex2.js":31,"./js/bitflyer.js":32,"./js/bitforex.js":33,"./js/bitget.js":34,"./js/bithumb.js":35,"./js/bitkk.js":36,"./js/bitmart.js":37,"./js/bitmex.js":38,"./js/bitpanda.js":39,"./js/bitso.js":40,"./js/bitstamp.js":41,"./js/bitstamp1.js":42,"./js/bittrex.js":43,"./js/bitvavo.js":44,"./js/bitz.js":45,"./js/bl3p.js":46,"./js/bleutrade.js":47,"./js/braziliex.js":48,"./js/btcalpha.js":49,"./js/btcbox.js":50,"./js/btcmarkets.js":51,"./js/btctradeua.js":52,"./js/btcturk.js":53,"./js/buda.js":54,"./js/bw.js":55,"./js/bybit.js":56,"./js/bytetrade.js":57,"./js/cdax.js":58,"./js/cex.js":59,"./js/coinbase.js":60,"./js/coinbaseprime.js":61,"./js/coinbasepro.js":62,"./js/coincheck.js":63,"./js/coinegg.js":64,"./js/coinex.js":65,"./js/coinfalcon.js":66,"./js/coinfloor.js":67,"./js/coingi.js":68,"./js/coinmarketcap.js":69,"./js/coinmate.js":70,"./js/coinone.js":71,"./js/coinspot.js":72,"./js/crex24.js":73,"./js/currencycom.js":74,"./js/delta.js":75,"./js/deribit.js":76,"./js/digifinex.js":77,"./js/equos.js":78,"./js/eterbase.js":79,"./js/exmo.js":80,"./js/exx.js":81,"./js/fcoin.js":82,"./js/fcoinjp.js":83,"./js/flowbtc.js":84,"./js/foxbit.js":85,"./js/ftx.js":86,"./js/gateio.js":87,"./js/gemini.js":88,"./js/gopax.js":89,"./js/hbtc.js":90,"./js/hitbtc.js":91,"./js/hollaex.js":92,"./js/huobijp.js":93,"./js/huobipro.js":94,"./js/idex.js":95,"./js/independentreserve.js":96,"./js/indodax.js":97,"./js/itbit.js":98,"./js/kraken.js":99,"./js/kucoin.js":100,"./js/kuna.js":101,"./js/lakebtc.js":102,"./js/latoken.js":103,"./js/lbank.js":104,"./js/liquid.js":105,"./js/luno.js":106,"./js/lykke.js":107,"./js/mercado.js":108,"./js/mixcoins.js":109,"./js/ndax.js":110,"./js/novadax.js":111,"./js/oceanex.js":112,"./js/okcoin.js":113,"./js/okex.js":114,"./js/paymium.js":115,"./js/phemex.js":116,"./js/poloniex.js":117,"./js/probit.js":118,"./js/qtrade.js":119,"./js/rightbtc.js":120,"./js/ripio.js":121,"./js/southxchange.js":122,"./js/stex.js":163,"./js/surbitcoin.js":164,"./js/therock.js":165,"./js/tidebit.js":166,"./js/tidex.js":167,"./js/timex.js":168,"./js/upbit.js":169,"./js/vbtc.js":170,"./js/vcc.js":171,"./js/wavesexchange.js":172,"./js/whitebit.js":173,"./js/xbtce.js":174,"./js/xena.js":175,"./js/yobit.js":176,"./js/zaif.js":177,"./js/zb.js":178}],3:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -192,6 +187,7 @@ module.exports = Object.assign ({ version, Exchange, 'exchanges': Object.keys (e const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, ExchangeNotAvailable, OrderNotFound, InvalidOrder, CancelPending, RateLimitExceeded, InsufficientFunds, BadRequest, BadSymbol, PermissionDenied } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -222,6 +218,7 @@ module.exports = class aax extends Exchange { 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, + 'fetchStatus': true, 'fetchTicker': 'emulated', 'fetchTickers': true, 'fetchTrades': true, @@ -420,6 +417,37 @@ module.exports = class aax extends Exchange { }); } + async fetchStatus (params = {}) { + const response = await this.publicGetAnnouncementMaintenance (params); + // + // { + // "code": 1, + // "data": { + // "startTime":"2020-06-25T02:15:00.000Z", + // "endTime":"2020-06-25T02:45:00.000Z", + // "description":"Spot Trading :UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45),Futures Trading: UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45).We apologize for any inconvenience caused. Thank you for your patience and understanding.Should you have any enquiries, please do not hesitate our live chat support or via email at cs@aax.com." + // }, + // "message":"success", + // "ts":1593043237000 + // } + // + const data = this.safeValue (response, 'data', {}); + const timestamp = this.milliseconds (); + const startTime = this.parse8601 (this.safeString (data, 'startTime')); + const endTime = this.parse8601 (this.safeString (data, 'endTime')); + const update = { + 'updated': this.safeInteger (response, 'ts', timestamp), + }; + if (endTime !== undefined) { + const startTimeIsOk = (startTime === undefined) ? true : (timestamp < startTime); + const isOk = (timestamp > endTime) || startTimeIsOk; + update['eta'] = endTime; + update['status'] = isOk ? 'ok' : 'maintenance'; + } + this.status = this.extend (this.status, update); + return this.status; + } + async fetchMarkets (params = {}) { const response = await this.publicGetInstruments (params); // @@ -505,8 +533,8 @@ module.exports = class aax extends Exchange { const quote = this.safeCurrencyCode (quoteId); const status = this.safeString (market, 'status'); const active = (status === 'enable'); - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); const type = this.safeString (market, 'type'); let inverse = undefined; let linear = undefined; @@ -524,8 +552,8 @@ module.exports = class aax extends Exchange { symbol = base + '/' + quote; } const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; result.push ({ 'id': id, @@ -583,8 +611,8 @@ module.exports = class aax extends Exchange { const timestamp = this.safeInteger (ticker, 't'); const marketId = this.safeString (ticker, 's'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'c'); - const open = this.safeFloat (ticker, 'o'); + const last = this.safeNumber (ticker, 'c'); + const open = this.safeNumber (ticker, 'o'); let change = undefined; let percentage = undefined; let average = undefined; @@ -595,13 +623,13 @@ module.exports = class aax extends Exchange { } average = this.sum (last, open) / 2; } - const quoteVolume = this.safeFloat (ticker, 'v'); + const quoteVolume = this.safeNumber (ticker, 'v'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'h'), - 'low': this.safeFloat (ticker, 'l'), + 'high': this.safeNumber (ticker, 'h'), + 'low': this.safeNumber (ticker, 'l'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -748,8 +776,8 @@ module.exports = class aax extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let price = this.safeFloat2 (trade, 'p', 'filledPrice'); - const amount = this.safeFloat2 (trade, 'q', 'filledQty'); + let priceString = this.safeString2 (trade, 'p', 'filledPrice'); + const amountString = this.safeString2 (trade, 'q', 'filledQty'); const orderId = this.safeString (trade, 'orderID'); const isTaker = this.safeValue (trade, 'taker'); let takerOrMaker = undefined; @@ -763,17 +791,15 @@ module.exports = class aax extends Exchange { side = 'sell'; } if (side === undefined) { - side = (price > 0) ? 'buy' : 'sell'; - } - side = (price > 0) ? 'buy' : 'sell'; - price = Math.abs (price); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; + side = (priceString[0] === '-') ? 'sell' : 'buy'; } + priceString = (priceString[0] === '-') ? priceString.slice (1) : priceString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderType = this.parseOrderType (this.safeString (trade, 'orderType')); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -841,11 +867,11 @@ module.exports = class aax extends Exchange { // return [ this.safeTimestamp (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -930,12 +956,12 @@ module.exports = class aax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'unavailable'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'unavailable'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -963,7 +989,7 @@ module.exports = class aax extends Exchange { request['clOrdID'] = clientOrderId; params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { if ((orderType === 'STOP-LIMIT') || (orderType === 'STOP')) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders'); @@ -1081,7 +1107,7 @@ module.exports = class aax extends Exchange { // 'price': this.priceToPrecision (symbol, price), // 'stopPrice': this.priceToPrecision (symbol, stopPrice), }; - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1718,15 +1744,18 @@ module.exports = class aax extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const price = this.safeFloat (order, 'price'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const price = this.safeNumber (order, 'price'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'Post-Only'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeString (order, 'leavesQty'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + let remaining = this.safeNumber (order, 'leavesQty'); + if ((filled === 0) && (remaining === 0)) { + remaining = undefined; + } let cost = undefined; let lastTradeTimestamp = undefined; if (filled !== undefined) { @@ -1741,7 +1770,7 @@ module.exports = class aax extends Exchange { } } let fee = undefined; - const feeCost = this.safeFloat (order, 'commission'); + const feeCost = this.safeNumber (order, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -1970,496 +1999,7 @@ module.exports = class aax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],4:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { InsufficientFunds, OrderNotFound } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class acx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'acx', - 'name': 'ACX', - 'countries': [ 'AU' ], - 'rateLimit': 1000, - 'version': 'v2', - 'has': { - 'cancelOrder': true, - 'CORS': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchMarkets': true, - 'fetchOHLCV': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTime': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '12h': '720', - '1d': '1440', - '3d': '4320', - '1w': '10080', - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg', - 'extension': '.json', - 'api': 'https://acx.io/api', - 'www': 'https://acx.io', - 'doc': 'https://acx.io/documents/api_v2', - }, - 'api': { - 'public': { - 'get': [ - 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. - 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator - 'k', // Get OHLC(k line) of specific market - 'markets', // Get all available markets - 'order_book', // Get the order book of specified market - 'order_book/{market}', - 'tickers', // Get ticker of all markets - 'tickers/{market}', // Get ticker of specific market - 'timestamp', // Get server current time, in seconds since Unix epoch - 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. - 'trades/{market}', - ], - }, - 'private': { - 'get': [ - 'members/me', // Get your profile and accounts info - 'deposits', // Get your deposits history - 'deposit', // Get details of specific deposit - 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. - 'orders', // Get your orders, results is paginated - 'order', // Get information of specified order - 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. - 'withdraws', // Get your cryptocurrency withdraws - 'withdraw', // Get your cryptocurrency withdraw - ], - 'post': [ - 'orders', // Create a Sell/Buy order - 'orders/multi', // Create multiple sell/buy orders - 'orders/clear', // Cancel all my orders - 'order/delete', // Cancel an order - 'withdraw', // Create a withdraw - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': false, - 'percentage': true, - 'maker': 0.2 / 100, - 'taker': 0.2 / 100, - }, - 'funding': { - 'tierBased': false, - 'percentage': true, - 'withdraw': {}, // There is only 1% fee on withdrawals to your bank account. - }, - }, - 'commonCurrencies': { - 'PLA': 'Plair', - }, - 'exceptions': { - '2002': InsufficientFunds, - '2003': OrderNotFound, - }, - }); - } - - async fetchMarkets (params = {}) { - const markets = await this.publicGetMarkets (params); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = market['id']; - const symbol = market['name']; - let baseId = this.safeString (market, 'base_unit'); - let quoteId = this.safeString (market, 'quote_unit'); - if ((baseId === undefined) || (quoteId === undefined)) { - const ids = symbol.split ('/'); - baseId = ids[0].toLowerCase (); - quoteId = ids[1].toLowerCase (); - } - let base = baseId.toUpperCase (); - let quote = quoteId.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - // todo: find out their undocumented precision and limits - const precision = { - 'amount': 8, - 'price': 8, - }; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'precision': precision, - 'info': market, - 'active': undefined, - 'limits': this.limits, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetMembersMe (params); - const balances = this.safeValue (response, 'accounts'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 300 - } - const orderbook = await this.publicGetDepth (this.extend (request, params)); - const timestamp = this.safeTimestamp (orderbook, 'timestamp'); - return this.parseOrderBook (orderbook, timestamp); - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.safeTimestamp (ticker, 'at'); - ticker = ticker['ticker']; - let symbol = undefined; - if (market) { - symbol = market['symbol']; - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetTickers (params); - const ids = Object.keys (response); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let market = undefined; - let symbol = id; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } else { - let base = id.slice (0, 3); - let quote = id.slice (3, 6); - base = base.toUpperCase (); - quote = quote.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - symbol = base + '/' + quote; - } - result[symbol] = this.parseTicker (response[id], market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTickersMarket (this.extend (request, params)); - return this.parseTicker (response, market); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const id = this.safeString (trade, 'tid'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': undefined, - 'side': undefined, - 'order': undefined, - 'takerOrMaker': undefined, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), - 'cost': this.safeFloat (trade, 'funds'), - 'fee': undefined, - }; - } - - async fetchTime (params = {}) { - const response = await this.publicGetTimestamp (params); - // - // 1594911427 - // - return response * 1000; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - return [ - this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (limit === undefined) { - limit = 500; // default is 30 - } - const request = { - 'market': market['id'], - 'period': this.timeframes[timeframe], - 'limit': limit, - }; - if (since !== undefined) { - request['timestamp'] = parseInt (since / 1000); - } - const response = await this.publicGetK (this.extend (request, params)); - return this.parseOHLCVs (response, market, timeframe, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'done': 'closed', - 'wait': 'open', - 'cancel': 'canceled', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - const marketId = this.safeString (order, 'market'); - const symbol = this.safeSymbol (marketId, market); - const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const status = this.parseOrderStatus (this.safeString (order, 'state')); - const type = this.safeString (order, 'type'); - const side = this.safeString (order, 'side'); - const id = this.safeString (order, 'id'); - return { - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': this.safeFloat (order, 'price'), - 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'volume'), - 'filled': this.safeFloat (order, 'executed_volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'trades': undefined, - 'fee': undefined, - 'info': order, - 'cost': undefined, - 'average': undefined, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': parseInt (id), - }; - const response = await this.privateGetOrder (this.extend (request, params)); - return this.parseOrder (response); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'market': this.marketId (symbol), - 'side': side, - 'volume': amount.toString (), - 'ord_type': type, - }; - if (type === 'limit') { - request['price'] = price.toString (); - } - const response = await this.privatePostOrders (this.extend (request, params)); - const marketId = this.safeValue (response, 'market'); - const market = this.safeValue (this.markets_by_id, marketId); - return this.parseOrder (response, market); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - const response = await this.privatePostOrderDelete (this.extend (request, params)); - const order = this.parseOrder (response); - const status = order['status']; - if (status === 'closed' || status === 'canceled') { - throw new OrderNotFound (this.id + ' ' + this.json (order)); - } - return order; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - // they have XRP but no docs on memo/tag - const request = { - 'currency': currency['id'], - 'sum': amount, - 'address': address, - }; - const response = await this.privatePostWithdraw (this.extend (request, params)); - // withdrawal response is undocumented - return { - 'info': response, - 'id': undefined, - }; - } - - nonce () { - return this.milliseconds (); - } - - encodeParams (params) { - if ('orders' in params) { - const orders = params['orders']; - let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); - for (let i = 0; i < orders.length; i++) { - const order = orders[i]; - const keys = Object.keys (order); - for (let k = 0; k < keys.length; k++) { - const key = keys[k]; - const value = order[key]; - query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); - } - } - return query; - } - return this.urlencode (this.keysort (params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let request = '/api/' + this.version + '/' + this.implodeParams (path, params); - if ('extension' in this.urls) { - request += this.urls['extension']; - } - const query = this.omit (params, this.extractParams (path)); - let url = this.urls['api'] + request; - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce ().toString (); - const query = this.encodeParams (this.extend ({ - 'access_key': this.apiKey, - 'tonce': nonce, - }, params)); - const auth = method + '|' + request + '|' + query; - const signed = this.hmac (this.encode (auth), this.encode (this.secret)); - const suffix = query + '&signature=' + signed; - if (method === 'GET') { - url += '?' + suffix; - } else { - body = suffix; - headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; - } - if (code === 400) { - const error = this.safeValue (response, 'error'); - const errorCode = this.safeString (error, 'code'); - const feedback = this.id + ' ' + this.json (response); - this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); - // fallback to default error handler - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],5:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],4:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -2467,6 +2007,7 @@ module.exports = class acx extends Exchange { const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, BadSymbol, InvalidOrder, PermissionDenied, InvalidAddress, AuthenticationError, InvalidNonce, BadRequest, InsufficientFunds, OrderNotFound } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -2655,8 +2196,8 @@ module.exports = class aofex extends Exchange { const symbol = base + '/' + quote; const numericId = this.safeInteger (market, 'id'); const precision = this.safeValue (precisions, id, {}); - const makerFee = this.safeFloat (market, 'maker_fee'); - const takerFee = this.safeFloat (market, 'taker_fee'); + const makerFee = this.safeNumber (market, 'maker_fee'); + const takerFee = this.safeNumber (market, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -2674,12 +2215,12 @@ module.exports = class aofex extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -2707,11 +2248,11 @@ module.exports = class aofex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -2790,11 +2331,11 @@ module.exports = class aofex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -2817,8 +2358,8 @@ module.exports = class aofex extends Exchange { return { 'info': response, 'symbol': symbol, - 'maker': this.safeFloat (result, 'fromFee'), - 'taker': this.safeFloat (result, 'toFee'), + 'maker': this.safeNumber (result, 'fromFee'), + 'taker': this.safeNumber (result, 'toFee'), }; } @@ -2875,8 +2416,8 @@ module.exports = class aofex extends Exchange { if (market) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); let change = undefined; if (symbol !== undefined) { change = parseFloat (this.priceToPrecision (symbol, last - open)); @@ -2885,8 +2426,8 @@ module.exports = class aofex extends Exchange { } const average = this.sum (last, open) / 2; const percentage = change / open * 100; - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); let vwap = this.vwap (baseVolume, quoteVolume); if (vwap !== undefined) { vwap = parseFloat (this.priceToPrecision (symbol, vwap)); @@ -2895,8 +2436,8 @@ module.exports = class aofex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -3014,13 +2555,15 @@ module.exports = class aofex extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'number'); - let cost = this.safeFloat (trade, 'total_price'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'number'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total_price'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -3164,21 +2707,21 @@ module.exports = class aofex extends Exchange { const orderType = this.safeString (order, 'type'); const type = (orderType === '2') ? 'limit' : 'market'; const side = this.safeString (order, 'side'); - // const amount = this.safeFloat (order, 'number'); - // const price = this.safeFloat (order, 'price'); + // const amount = this.safeNumber (order, 'number'); + // const price = this.safeNumber (order, 'price'); let cost = undefined; let price = undefined; let amount = undefined; let average = undefined; - const number = this.safeFloat (order, 'number'); - const totalPrice = this.safeFloat (order, 'total_price'); + const number = this.safeNumber (order, 'number'); + const totalPrice = this.safeNumber (order, 'total_price'); if (type === 'limit') { amount = number; - price = this.safeFloat (order, 'price'); + price = this.safeNumber (order, 'price'); } else { - average = this.safeFloat (order, 'deal_price'); + average = this.safeNumber (order, 'deal_price'); if (side === 'buy') { - amount = this.safeFloat (order, 'deal_number'); + amount = this.safeNumber (order, 'deal_number'); } else { amount = number; } @@ -3561,7 +3104,1693 @@ module.exports = class aofex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],6:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],5:[function(require,module,exports){ +'use strict'; + +// --------------------------------------------------------------------------- + +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); + +// --------------------------------------------------------------------------- + +module.exports = class ascendex extends Exchange { + describe () { + return this.deepExtend (super.describe (), { + 'id': 'ascendex', + 'name': 'AscendEX', + 'countries': [ 'SG', 'CN' ], // Singapore, China + 'rateLimit': 500, + // new metainfo interface + 'has': { + 'CORS': false, + 'fetchMarkets': true, + 'fetchCurrencies': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchOHLCV': true, + 'fetchTrades': true, + 'fetchAccounts': true, + 'fetchBalance': true, + 'createOrder': true, + 'cancelOrder': true, + 'cancelAllOrders': true, + 'fetchDepositAddress': true, + 'fetchTransactions': true, + 'fetchDeposits': true, + 'fetchWithdrawals': true, + 'fetchOrder': true, + 'fetchOrders': true, + 'fetchOpenOrders': true, + 'fetchClosedOrders': true, + }, + 'timeframes': { + '1m': '1', + '5m': '5', + '15m': '15', + '30m': '30', + '1h': '60', + '2h': '120', + '4h': '240', + '6h': '360', + '12h': '720', + '1d': '1d', + '1w': '1w', + '1M': '1m', + }, + 'version': 'v1', + 'urls': { + 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg', + 'api': 'https://ascendex.com', + 'test': 'https://bitmax-test.io', + 'www': 'https://ascendex.com', + 'doc': [ + 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', + ], + 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate', + 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', + }, + 'api': { + 'public': { + 'get': [ + 'assets', + 'products', + 'ticker', + 'barhist/info', + 'barhist', + 'depth', + 'trades', + 'cash/assets', // not documented + 'cash/products', // not documented + 'margin/assets', // not documented + 'margin/products', // not documented + 'futures/collateral', + 'futures/contracts', + 'futures/ref-px', + 'futures/market-data', + 'futures/funding-rates', + ], + }, + 'accountCategory': { + 'get': [ + 'balance', + 'order/open', + 'order/status', + 'order/hist/current', + 'risk', + ], + 'post': [ + 'order', + 'order/batch', + ], + 'delete': [ + 'order', + 'order/all', + 'order/batch', + ], + }, + 'accountGroup': { + 'get': [ + 'cash/balance', + 'margin/balance', + 'margin/risk', + 'transfer', + 'futures/collateral-balance', + 'futures/position', + 'futures/risk', + 'futures/funding-payments', + 'order/hist', + ], + 'post': [ + 'futures/transfer/deposit', + 'futures/transfer/withdraw', + ], + }, + 'private': { + 'get': [ + 'info', + 'wallet/transactions', + 'wallet/deposit/address', // not documented + ], + }, + }, + 'fees': { + 'trading': { + 'feeSide': 'get', + 'tierBased': true, + 'percentage': true, + 'taker': 0.002, + 'maker': 0.002, + }, + }, + 'precisionMode': TICK_SIZE, + 'options': { + 'account-category': 'cash', // 'cash'/'margin'/'futures' + 'account-group': undefined, + 'fetchClosedOrders': { + 'method': 'accountGroupGetOrderHist', // 'accountGroupGetAccountCategoryOrderHistCurrent' + }, + }, + 'exceptions': { + 'exact': { + // not documented + '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"} + '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"} + '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"} + '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."} + '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'} + '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' } + '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."} + // documented + '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid + '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing + '100003': BadRequest, // KEY_CONFLICT The same key exists already + '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument + '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument + '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid + '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption + '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request + '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request + '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account + '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp + '100012': BadRequest, // INVALID_STR_FORMAT String format does not + '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input + '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error + '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object + '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed + '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times + '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist + '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly + '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist + '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error + '200007': ExchangeError, // CODE_NOT_FOUND + '200008': ExchangeError, // CODE_EXPIRED Code expired + '200009': ExchangeError, // CODE_MISMATCH Code does not match + '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword + '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly + '200012': ExchangeError, // FAKE_COKE_VERIFY + '200013': ExchangeError, // SECURITY_ALERT Provide security alert message + '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw. + '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation + '300001': InvalidOrder, // INVALID_PRICE Order price is invalid + '300002': InvalidOrder, // INVALID_QTY Order size is invalid + '300003': InvalidOrder, // INVALID_SIDE Order side is invalid + '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large + '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid + '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid + '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid + '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid + '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset + '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading + '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange + '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request + '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset + '300021': InvalidOrder, // TRADING_DISABLED Trading is disabled on account or asset + '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading + '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance + '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading + '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high + '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading + '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price + '510001': ExchangeError, // SERVER_ERROR Something wrong with server. + '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass + }, + 'broad': {}, + }, + 'commonCurrencies': { + 'BOND': 'BONDED', + 'BTCBEAR': 'BEAR', + 'BTCBULL': 'BULL', + }, + }); + } + + getAccount (params = {}) { + // get current or provided bitmax sub-account + const account = this.safeValue (params, 'account', this.options['account']); + return account.toLowerCase ().capitalize (); + } + + async fetchCurrencies (params = {}) { + const assets = await this.publicGetAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode" : "LTCBULL", + // "assetName" : "3X Long LTC Token", + // "precisionScale" : 9, + // "nativeScale" : 4, + // "withdrawalFee" : "0.2", + // "minWithdrawalAmt" : "1.0", + // "status" : "Normal" + // }, + // ] + // } + // + const margin = await this.publicGetMarginAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode":"BTT", + // "borrowAssetCode":"BTT-B", + // "interestAssetCode":"BTT-I", + // "nativeScale":0, + // "numConfirmations":1, + // "withdrawFee":"100.0", + // "minWithdrawalAmt":"1000.0", + // "statusCode":"Normal", + // "statusMessage":"", + // "interestRate":"0.001" + // } + // ] + // } + // + const cash = await this.publicGetCashAssets (params); + // + // { + // "code":0, + // "data":[ + // { + // "assetCode":"LTCBULL", + // "nativeScale":4, + // "numConfirmations":20, + // "withdrawFee":"0.2", + // "minWithdrawalAmt":"1.0", + // "statusCode":"Normal", + // "statusMessage":"" + // } + // ] + // } + // + const assetsData = this.safeValue (assets, 'data', []); + const marginData = this.safeValue (margin, 'data', []); + const cashData = this.safeValue (cash, 'data', []); + const assetsById = this.indexBy (assetsData, 'assetCode'); + const marginById = this.indexBy (marginData, 'assetCode'); + const cashById = this.indexBy (cashData, 'assetCode'); + const dataById = this.deepExtend (assetsById, marginById, cashById); + const ids = Object.keys (dataById); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + const currency = dataById[id]; + const code = this.safeCurrencyCode (id); + const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); + // why would the exchange API have different names for the same field + const fee = this.safeNumber2 (currency, 'withdrawFee', 'withdrawalFee'); + const status = this.safeString2 (currency, 'status', 'statusCode'); + const active = (status === 'Normal'); + const margin = ('borrowAssetCode' in currency); + result[code] = { + 'id': id, + 'code': code, + 'info': currency, + 'type': undefined, + 'margin': margin, + 'name': this.safeString (currency, 'assetName'), + 'active': active, + 'fee': fee, + 'precision': precision, + 'limits': { + 'amount': { + 'min': Math.pow (10, -precision), + 'max': undefined, + }, + 'price': { + 'min': Math.pow (10, -precision), + 'max': undefined, + }, + 'cost': { + 'min': undefined, + 'max': undefined, + }, + 'withdraw': { + 'min': this.safeNumber (currency, 'minWithdrawalAmt'), + 'max': undefined, + }, + }, + }; + } + return result; + } + + async fetchMarkets (params = {}) { + const products = await this.publicGetProducts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"LBA/BTC", + // "baseAsset":"LBA", + // "quoteAsset":"BTC", + // "status":"Normal", + // "minNotional":"0.000625", + // "maxNotional":"6.25", + // "marginTradable":false, + // "commissionType":"Quote", + // "commissionReserveRate":"0.001", + // "tickSize":"0.000000001", + // "lotSize":"1" + // }, + // ] + // } + // + const cash = await this.publicGetCashProducts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"QTUM/BTC", + // "domain":"BTC", + // "tradingStartTime":1569506400000, + // "collapseDecimals":"0.0001,0.000001,0.00000001", + // "minQty":"0.000000001", + // "maxQty":"1000000000", + // "minNotional":"0.000625", + // "maxNotional":"12.5", + // "statusCode":"Normal", + // "statusMessage":"", + // "tickSize":"0.00000001", + // "useTick":false, + // "lotSize":"0.1", + // "useLot":false, + // "commissionType":"Quote", + // "commissionReserveRate":"0.001", + // "qtyScale":1, + // "priceScale":8, + // "notionalScale":4 + // } + // ] + // } + // + const futures = await this.publicGetFuturesContracts (params); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"BTC-PERP", + // "tradingStartTime":1579701600000, + // "collapseDecimals":"1,0.1,0.01", + // "minQty":"0.000000001", + // "maxQty":"1000000000", + // "minNotional":"5", + // "maxNotional":"1000000", + // "statusCode":"Normal", + // "statusMessage":"", + // "tickSize":"0.25", + // "lotSize":"0.0001", + // "priceScale":2, + // "qtyScale":4, + // "notionalScale":2 + // } + // ] + // } + // + const productsData = this.safeValue (products, 'data', []); + const productsById = this.indexBy (productsData, 'symbol'); + const cashData = this.safeValue (cash, 'data', []); + const futuresData = this.safeValue (futures, 'data', []); + const cashAndFuturesData = this.arrayConcat (cashData, futuresData); + const cashAndFuturesById = this.indexBy (cashAndFuturesData, 'symbol'); + const dataById = this.deepExtend (productsById, cashAndFuturesById); + const ids = Object.keys (dataById); + const result = []; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + const market = dataById[id]; + const baseId = this.safeString (market, 'baseAsset'); + const quoteId = this.safeString (market, 'quoteAsset'); + const base = this.safeCurrencyCode (baseId); + const quote = this.safeCurrencyCode (quoteId); + const precision = { + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), + }; + const status = this.safeString (market, 'status'); + const active = (status === 'Normal'); + const type = ('useLot' in market) ? 'spot' : 'future'; + const spot = (type === 'spot'); + const future = (type === 'future'); + let symbol = id; + if (!future) { + symbol = base + '/' + quote; + } + result.push ({ + 'id': id, + 'symbol': symbol, + 'base': base, + 'quote': quote, + 'baseId': baseId, + 'quoteId': quoteId, + 'info': market, + 'type': type, + 'spot': spot, + 'future': future, + 'active': active, + 'precision': precision, + 'limits': { + 'amount': { + 'min': this.safeNumber (market, 'minQty'), + 'max': this.safeNumber (market, 'maxQty'), + }, + 'price': { + 'min': this.safeNumber (market, 'tickSize'), + 'max': undefined, + }, + 'cost': { + 'min': this.safeNumber (market, 'minNotional'), + 'max': this.safeNumber (market, 'maxNotional'), + }, + }, + }); + } + return result; + } + + async fetchAccounts (params = {}) { + let accountGroup = this.safeString (this.options, 'account-group'); + let response = undefined; + if (accountGroup === undefined) { + response = await this.privateGetInfo (params); + // + // { + // "code":0, + // "data":{ + // "email":"igor.kroitor@gmail.com", + // "accountGroup":8, + // "viewPermission":true, + // "tradePermission":true, + // "transferPermission":true, + // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"], + // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"], + // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"], + // "userUID":"U6491137460" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + accountGroup = this.safeString (data, 'accountGroup'); + this.options['account-group'] = accountGroup; + } + return [ + { + 'id': accountGroup, + 'type': undefined, + 'currency': undefined, + 'info': response, + }, + ]; + } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchBalance', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeString (account, 'id'); + const request = { + 'account-group': accountGroup, + }; + let method = 'accountCategoryGetBalance'; + if (accountCategory === 'futures') { + method = 'accountGroupGetFuturesCollateralBalance'; + } else { + request['account-category'] = accountCategory; + } + const response = await this[method] (this.extend (request, params)); + // + // cash + // + // { + // 'code': 0, + // 'data': [ + // { + // 'asset': 'BCHSV', + // 'totalBalance': '64.298000048', + // 'availableBalance': '64.298000048', + // }, + // ] + // } + // + // margin + // + // { + // 'code': 0, + // 'data': [ + // { + // 'asset': 'BCHSV', + // 'totalBalance': '64.298000048', + // 'availableBalance': '64.298000048', + // 'borrowed': '0', + // 'interest': '0', + // }, + // ] + // } + // + // futures + // + // { + // "code":0, + // "data":[ + // {"asset":"BTC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"9456.59"}, + // {"asset":"ETH","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"235.95"}, + // {"asset":"USDT","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"}, + // {"asset":"USDC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00035"}, + // {"asset":"PAX","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00045"}, + // {"asset":"USDTR","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"} + // ] + // } + // + const result = { 'info': response }; + const balances = this.safeValue (response, 'data', []); + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); + const account = this.account (); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async fetchOrderBook (symbol, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + const response = await this.publicGetDepth (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "m":"depth-snapshot", + // "symbol":"BTC-PERP", + // "data":{ + // "ts":1590223998202, + // "seqnum":115444921, + // "asks":[ + // ["9207.5","18.2383"], + // ["9207.75","18.8235"], + // ["9208","10.7873"], + // ], + // "bids":[ + // ["9207.25","0.4009"], + // ["9207","0.003"], + // ["9206.5","0.003"], + // ] + // } + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const orderbook = this.safeValue (data, 'data', {}); + const timestamp = this.safeInteger (orderbook, 'ts'); + const result = this.parseOrderBook (orderbook, timestamp); + result['nonce'] = this.safeInteger (orderbook, 'seqnum'); + return result; + } + + parseTicker (ticker, market = undefined) { + // + // { + // "symbol":"QTUM/BTC", + // "open":"0.00016537", + // "close":"0.00019077", + // "high":"0.000192", + // "low":"0.00016537", + // "volume":"846.6", + // "ask":["0.00018698","26.2"], + // "bid":["0.00018408","503.7"], + // "type":"spot" + // } + // + const timestamp = undefined; + const marketId = this.safeString (ticker, 'symbol'); + let symbol = undefined; + if (marketId in this.markets_by_id) { + market = this.markets_by_id[marketId]; + } else if (marketId !== undefined) { + const type = this.safeString (ticker, 'type'); + if (type === 'spot') { + const [ baseId, quoteId ] = marketId.split ('/'); + const base = this.safeCurrencyCode (baseId); + const quote = this.safeCurrencyCode (quoteId); + symbol = base + '/' + quote; + } + } + if ((symbol === undefined) && (market !== undefined)) { + symbol = market['symbol']; + } + const close = this.safeNumber (ticker, 'close'); + const bid = this.safeValue (ticker, 'bid', []); + const ask = this.safeValue (ticker, 'ask', []); + const open = this.safeNumber (ticker, 'open'); + let change = undefined; + let percentage = undefined; + let average = undefined; + if ((open !== undefined) && (close !== undefined)) { + change = close - open; + if (open > 0) { + percentage = change / open * 100; + } + average = this.sum (open, close) / 2; + } + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 0), + 'bidVolume': this.safeNumber (bid, 1), + 'ask': this.safeNumber (ask, 0), + 'askVolume': this.safeNumber (ask, 1), + 'vwap': undefined, + 'open': open, + 'close': close, + 'last': close, + 'previousClose': undefined, // previous day close + 'change': change, + 'percentage': percentage, + 'average': average, + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + const response = await this.publicGetTicker (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "symbol":"BTC-PERP", // or "BTC/USDT" + // "open":"9073", + // "close":"9185.75", + // "high":"9185.75", + // "low":"9185.75", + // "volume":"576.8334", + // "ask":["9185.75","15.5863"], + // "bid":["9185.5","0.003"], + // "type":"derivatives", // or "spot" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + return this.parseTicker (data, market); + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (symbols !== undefined) { + const marketIds = this.marketIds (symbols); + request['symbol'] = marketIds.join (','); + } + const response = await this.publicGetTicker (this.extend (request, params)); + // + // { + // "code":0, + // "data":[ + // { + // "symbol":"QTUM/BTC", + // "open":"0.00016537", + // "close":"0.00019077", + // "high":"0.000192", + // "low":"0.00016537", + // "volume":"846.6", + // "ask":["0.00018698","26.2"], + // "bid":["0.00018408","503.7"], + // "type":"spot" + // } + // ] + // } + // + const data = this.safeValue (response, 'data', []); + return this.parseTickers (data, symbols); + } + + parseOHLCV (ohlcv, market = undefined) { + // + // { + // "m":"bar", + // "s":"BTC/USDT", + // "data":{ + // "i":"1", + // "ts":1590228000000, + // "o":"9139.59", + // "c":"9131.94", + // "h":"9139.99", + // "l":"9121.71", + // "v":"25.20648" + // } + // } + // + const data = this.safeValue (ohlcv, 'data', {}); + return [ + this.safeInteger (data, 'ts'), + this.safeNumber (data, 'o'), + this.safeNumber (data, 'h'), + this.safeNumber (data, 'l'), + this.safeNumber (data, 'c'), + this.safeNumber (data, 'v'), + ]; + } + + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + 'interval': this.timeframes[timeframe], + }; + // if since and limit are not specified + // the exchange will return just 1 last candle by default + const duration = this.parseTimeframe (timeframe); + const options = this.safeValue (this.options, 'fetchOHLCV', {}); + const defaultLimit = this.safeInteger (options, 'limit', 500); + if (since !== undefined) { + request['from'] = since; + if (limit === undefined) { + limit = defaultLimit; + } else { + limit = Math.min (limit, defaultLimit); + } + request['to'] = this.sum (since, limit * duration * 1000, 1); + } else if (limit !== undefined) { + request['n'] = limit; // max 500 + } + const response = await this.publicGetBarhist (this.extend (request, params)); + // + // { + // "code":0, + // "data":[ + // { + // "m":"bar", + // "s":"BTC/USDT", + // "data":{ + // "i":"1", + // "ts":1590228000000, + // "o":"9139.59", + // "c":"9131.94", + // "h":"9139.99", + // "l":"9121.71", + // "v":"25.20648" + // } + // } + // ] + // } + // + const data = this.safeValue (response, 'data', []); + return this.parseOHLCVs (data, market, timeframe, since, limit); + } + + parseTrade (trade, market = undefined) { + // + // public fetchTrades + // + // { + // "p":"9128.5", // price + // "q":"0.0030", // quantity + // "ts":1590229002385, // timestamp + // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade + // "seqnum":180143985289898554 + // } + // + const timestamp = this.safeInteger (trade, 'ts'); + const priceString = this.safeString2 (trade, 'price', 'p'); + const amountString = this.safeString (trade, 'q'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const buyerIsMaker = this.safeValue (trade, 'bm', false); + const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; + const side = buyerIsMaker ? 'buy' : 'sell'; + let symbol = undefined; + if ((symbol === undefined) && (market !== undefined)) { + symbol = market['symbol']; + } + return { + 'info': trade, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'symbol': symbol, + 'id': undefined, + 'order': undefined, + 'type': undefined, + 'takerOrMaker': makerOrTaker, + 'side': side, + 'price': price, + 'amount': amount, + 'cost': cost, + 'fee': undefined, + }; + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'symbol': market['id'], + }; + if (limit !== undefined) { + request['n'] = limit; // max 100 + } + const response = await this.publicGetTrades (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "m":"trades", + // "symbol":"BTC-PERP", + // "data":[ + // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554}, + // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587}, + // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043} + // ] + // } + // } + // + const records = this.safeValue (response, 'data', []); + const trades = this.safeValue (records, 'data', []); + return this.parseTrades (trades, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'PendingNew': 'open', + 'New': 'open', + 'PartiallyFilled': 'open', + 'Filled': 'closed', + 'Canceled': 'canceled', + 'Rejected': 'rejected', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + // + // createOrder + // + // { + // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", + // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", + // "orderType": "Market", + // "symbol": "BTC/USDT", + // "timestamp": 1573576916201 + // } + // + // fetchOrder, fetchOpenOrders, fetchClosedOrders + // + // { + // "symbol": "BTC/USDT", + // "price": "8131.22", + // "orderQty": "0.00082", + // "orderType": "Market", + // "avgPx": "7392.02", + // "cumFee": "0.005152238", + // "cumFilledQty": "0.00082", + // "errorCode": "", + // "feeAsset": "USDT", + // "lastExecTime": 1575953151764, + // "orderId": "a16eee20b6750866943712zWEDdAjt3", + // "seqNum": 2623469, + // "side": "Buy", + // "status": "Filled", + // "stopPrice": "", + // "execInst": "NULL_VAL" + // } + // + // { + // "ac": "FUTURES", + // "accountId": "testabcdefg", + // "avgPx": "0", + // "cumFee": "0", + // "cumQty": "0", + // "errorCode": "NULL_VAL", + // "execInst": "NULL_VAL", + // "feeAsset": "USDT", + // "lastExecTime": 1584072844085, + // "orderId": "r170d21956dd5450276356bbtcpKa74", + // "orderQty": "1.1499", + // "orderType": "Limit", + // "price": "4000", + // "sendingTime": 1584072841033, + // "seqNum": 24105338, + // "side": "Buy", + // "status": "Canceled", + // "stopPrice": "", + // "symbol": "BTC-PERP" + // }, + // + const status = this.parseOrderStatus (this.safeString (order, 'status')); + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '/'); + const timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); + const lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const average = this.safeNumber (order, 'avgPx'); + const filled = this.safeNumber2 (order, 'cumFilledQty', 'cumQty'); + const id = this.safeString (order, 'orderId'); + let clientOrderId = this.safeString (order, 'id'); + if (clientOrderId !== undefined) { + if (clientOrderId.length < 1) { + clientOrderId = undefined; + } + } + const type = this.safeStringLower (order, 'orderType'); + const side = this.safeStringLower (order, 'side'); + const feeCost = this.safeNumber (order, 'cumFee'); + let fee = undefined; + if (feeCost !== undefined) { + const feeCurrencyId = this.safeString (order, 'feeAsset'); + const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); + fee = { + 'cost': feeCost, + 'currency': feeCurrencyCode, + }; + } + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ + 'info': order, + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': lastTradeTimestamp, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': price, + 'stopPrice': stopPrice, + 'amount': amount, + 'cost': undefined, + 'average': average, + 'filled': filled, + 'remaining': undefined, + 'status': status, + 'fee': fee, + 'trades': undefined, + }); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const market = this.market (symbol); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'createOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'symbol': market['id'], + 'time': this.milliseconds (), + 'orderQty': this.amountToPrecision (symbol, amount), + 'orderType': type, // "limit", "market", "stop_market", "stop_limit" + 'side': side, // "buy" or "sell" + // 'orderPrice': this.priceToPrecision (symbol, price), + // 'stopPrice': this.priceToPrecision (symbol, stopPrice), // required for stop orders + // 'postOnly': 'false', // 'false', 'true' + // 'timeInForce': 'GTC', // GTC, IOC, FOK + // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE + }; + if (clientOrderId !== undefined) { + request['id'] = clientOrderId; + params = this.omit (params, [ 'clientOrderId', 'id' ]); + } + if ((type === 'limit') || (type === 'stop_limit')) { + request['orderPrice'] = this.priceToPrecision (symbol, price); + } + if ((type === 'stop_limit') || (type === 'stop_market')) { + const stopPrice = this.safeNumber (params, 'stopPrice'); + if (stopPrice === undefined) { + throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); + } else { + request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); + params = this.omit (params, 'stopPrice'); + } + } + const response = await this.accountCategoryPostOrder (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "ac": "MARGIN", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "action": "place-order", + // "info": { + // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", + // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", + // "orderType": "Market", + // "symbol": "BTC/USDT", + // "timestamp": 1573576916201 + // }, + // "status": "Ack" + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const info = this.safeValue (data, 'info', {}); + return this.parseOrder (info, market); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'orderId': id, + }; + const response = await this.accountCategoryGetOrderStatus (this.extend (request, params)); + // + // { + // "code": 0, + // "accountCategory": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "data": [ + // { + // "symbol": "BTC/USDT", + // "price": "8131.22", + // "orderQty": "0.00082", + // "orderType": "Market", + // "avgPx": "7392.02", + // "cumFee": "0.005152238", + // "cumFilledQty": "0.00082", + // "errorCode": "", + // "feeAsset": "USDT", + // "lastExecTime": 1575953151764, + // "orderId": "a16eee20b6750866943712zWEDdAjt3", + // "seqNum": 2623469, + // "side": "Buy", + // "status": "Filled", + // "stopPrice": "", + // "execInst": "NULL_VAL" + // } + // ] + // } + // + const data = this.safeValue (response, 'data', {}); + return this.parseOrder (data); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + } + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'fetchOpenOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + }; + const response = await this.accountCategoryGetOrderOpen (this.extend (request, params)); + // + // { + // "ac": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "code": 0, + // "data": [ + // { + // "avgPx": "0", // Average filled price of the order + // "cumFee": "0", // cumulative fee paid for this order + // "cumFilledQty": "0", // cumulative filled quantity + // "errorCode": "", // error code; could be empty + // "feeAsset": "USDT", // fee asset + // "lastExecTime": 1576019723550, // The last execution time of the order + // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId + // "orderQty": "0.0083", // order quantity + // "orderType": "Limit", // order type + // "price": "7105", // order price + // "seqNum": 8193258, // sequence number + // "side": "Buy", // order side + // "status": "New", // order status on matching engine + // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty + // "symbol": "BTC/USDT", + // "execInst": "NULL_VAL" // execution instruction + // }, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + if (accountCategory === 'futures') { + return this.parseOrders (data, market, since, limit); + } + // a workaround for https://github.com/ccxt/ccxt/issues/7187 + const orders = []; + for (let i = 0; i < data.length; i++) { + const order = this.parseOrder (data[i], market); + orders.push (order); + } + return this.filterBySymbolSinceLimit (orders, symbol, since, limit); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + } + const defaultAccountCategory = this.safeString (this.options, 'account-category'); + const options = this.safeValue (this.options, 'fetchClosedOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + // 'category': accountCategory, + // 'symbol': market['id'], + // 'orderType': 'market', // optional, string + // 'side': 'buy', // or 'sell', optional, case insensitive. + // 'status': 'Filled', // "Filled", "Canceled", or "Rejected" + // 'startTime': exchange.milliseconds (), + // 'endTime': exchange.milliseconds (), + // 'page': 1, + // 'pageSize': 100, + }; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const method = this.safeValue (options, 'method', 'accountGroupGetOrderHist'); + if (method === 'accountGroupGetOrderHist') { + if (accountCategory !== undefined) { + request['category'] = accountCategory; + } + } else { + request['account-category'] = accountCategory; + } + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['pageSize'] = limit; + } + const response = await this[method] (this.extend (request, params)); + // + // accountCategoryGetOrderHistCurrent + // + // { + // "code":0, + // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda", + // "ac":"CASH", + // "data":[ + // { + // "seqNum":15561826728, + // "orderId":"a17294d305c0U6491137460bethu7kw9", + // "symbol":"ETH/USDT", + // "orderType":"Limit", + // "lastExecTime":1591635618200, + // "price":"200", + // "orderQty":"0.1", + // "side":"Buy", + // "status":"Canceled", + // "avgPx":"0", + // "cumFilledQty":"0", + // "stopPrice":"", + // "errorCode":"", + // "cumFee":"0", + // "feeAsset":"USDT", + // "execInst":"NULL_VAL" + // } + // ] + // } + // + // accountGroupGetOrderHist + // + // { + // "code": 0, + // "data": { + // "data": [ + // { + // "ac": "FUTURES", + // "accountId": "testabcdefg", + // "avgPx": "0", + // "cumFee": "0", + // "cumQty": "0", + // "errorCode": "NULL_VAL", + // "execInst": "NULL_VAL", + // "feeAsset": "USDT", + // "lastExecTime": 1584072844085, + // "orderId": "r170d21956dd5450276356bbtcpKa74", + // "orderQty": "1.1499", + // "orderType": "Limit", + // "price": "4000", + // "sendingTime": 1584072841033, + // "seqNum": 24105338, + // "side": "Buy", + // "status": "Canceled", + // "stopPrice": "", + // "symbol": "BTC-PERP" + // }, + // ], + // "hasNext": False, + // "limit": 500, + // "page": 1, + // "pageSize": 20 + // } + // } + // + let data = this.safeValue (response, 'data'); + const isArray = Array.isArray (data); + if (!isArray) { + data = this.safeValue (data, 'data', []); + } + return this.parseOrders (data, market, since, limit); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument'); + } + await this.loadMarkets (); + await this.loadAccounts (); + const market = this.market (symbol); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'cancelOrder', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'symbol': market['id'], + 'time': this.milliseconds (), + 'id': 'foobar', + }; + if (clientOrderId === undefined) { + request['orderId'] = id; + } else { + request['id'] = clientOrderId; + params = this.omit (params, [ 'clientOrderId', 'id' ]); + } + const response = await this.accountCategoryDeleteOrder (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "ac": "CASH", + // "action": "cancel-order", + // "status": "Ack", + // "info": { + // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23", + // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc", + // "orderType": "", // could be empty + // "symbol": "ETH/USDT", + // "timestamp": 1573594877822 + // } + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const info = this.safeValue (data, 'info', {}); + return this.parseOrder (info, market); + } + + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + await this.loadAccounts (); + const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); + const options = this.safeValue (this.options, 'cancelAllOrders', {}); + let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); + accountCategory = this.safeString (params, 'account-category', accountCategory); + params = this.omit (params, 'account-category'); + const account = this.safeValue (this.accounts, 0, {}); + const accountGroup = this.safeValue (account, 'id'); + const request = { + 'account-group': accountGroup, + 'account-category': accountCategory, + 'time': this.milliseconds (), + }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.accountCategoryDeleteOrderAll (this.extend (request, params)); + // + // { + // "code": 0, + // "data": { + // "ac": "CASH", + // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", + // "action": "cancel-all", + // "info": { + // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy", + // "orderId": "", + // "orderType": "NULL_VAL", + // "symbol": "", + // "timestamp": 1574118495462 + // }, + // "status": "Ack" + // } + // } + // + return response; + } + + parseDepositAddress (depositAddress, currency = undefined) { + // + // { + // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // destTag: "", + // tagType: "", + // tagId: "", + // chainName: "ERC20", + // numConfirmations: 20, + // withdrawalFee: 1, + // nativeScale: 4, + // tips: [] + // } + // + const address = this.safeString (depositAddress, 'address'); + const tagId = this.safeString (depositAddress, 'tagId'); + const tag = this.safeString (depositAddress, tagId); + this.checkAddress (address); + const code = (currency === undefined) ? undefined : currency['code']; + return { + 'currency': code, + 'address': address, + 'tag': tag, + 'info': depositAddress, + }; + } + + async fetchDepositAddress (code, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const chainName = this.safeString (params, 'chainName'); + params = this.omit (params, 'chainName'); + const request = { + 'asset': currency['id'], + }; + const response = await this.privateGetWalletDepositAddress (this.extend (request, params)); + // + // { + // "code":0, + // "data":{ + // "asset":"USDT", + // "assetName":"Tether", + // "address":[ + // { + // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6", + // "destTag":"", + // "tagType":"", + // "tagId":"", + // "chainName":"Omni", + // "numConfirmations":3, + // "withdrawalFee":4.7, + // "nativeScale":4, + // "tips":[] + // }, + // { + // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // "destTag":"", + // "tagType":"", + // "tagId":"", + // "chainName":"ERC20", + // "numConfirmations":20, + // "withdrawalFee":1.0, + // "nativeScale":4, + // "tips":[] + // } + // ] + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const addresses = this.safeValue (data, 'address', []); + const numAddresses = addresses.length; + let address = undefined; + if (numAddresses > 1) { + const addressesByChainName = this.indexBy (addresses, 'chainName'); + if (chainName === undefined) { + const chainNames = Object.keys (addressesByChainName); + const chains = chainNames.join (', '); + throw new ArgumentsRequired (this.id + ' fetchDepositAddress returned more than one address, a chainName parameter is required, one of ' + chains); + } + address = this.safeValue (addressesByChainName, chainName, {}); + } else { + // first address + address = this.safeValue (addresses, 0, {}); + } + const result = this.parseDepositAddress (address, currency); + return this.extend (result, { + 'info': response, + }); + } + + async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'txType': 'deposit', + }; + return await this.fetchTransactions (code, since, limit, this.extend (request, params)); + } + + async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'txType': 'withdrawal', + }; + return await this.fetchTransactions (code, since, limit, this.extend (request, params)); + } + + async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'asset': currency['id'], + // 'page': 1, + // 'pageSize': 20, + // 'startTs': this.milliseconds (), + // 'endTs': this.milliseconds (), + // 'txType': undefned, // deposit, withdrawal + }; + let currency = undefined; + if (code !== undefined) { + currency = this.currency (code); + request['asset'] = currency['id']; + } + if (since !== undefined) { + request['startTs'] = since; + } + if (limit !== undefined) { + request['pageSize'] = limit; + } + const response = await this.privateGetWalletTransactions (this.extend (request, params)); + // + // { + // code: 0, + // data: { + // data: [ + // { + // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", + // time: 1591606166000, + // asset: "USDT", + // transactionType: "deposit", + // amount: "25", + // commission: "0", + // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", + // status: "pending", + // numConfirmed: 8, + // numConfirmations: 20, + // destAddress: { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" } + // } + // ], + // page: 1, + // pageSize: 20, + // hasNext: false + // } + // } + // + const data = this.safeValue (response, 'data', {}); + const transactions = this.safeValue (data, 'data', []); + return this.parseTransactions (transactions, currency, since, limit); + } + + parseTransactionStatus (status) { + const statuses = { + 'reviewing': 'pending', + 'pending': 'pending', + 'confirmed': 'ok', + 'rejected': 'rejected', + }; + return this.safeString (statuses, status, status); + } + + parseTransaction (transaction, currency = undefined) { + // + // { + // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", + // time: 1591606166000, + // asset: "USDT", + // transactionType: "deposit", + // amount: "25", + // commission: "0", + // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", + // status: "pending", + // numConfirmed: 8, + // numConfirmations: 20, + // destAddress: { + // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", + // destTag: "..." // for currencies that have it + // } + // } + // + const id = this.safeString (transaction, 'requestId'); + const amount = this.safeNumber (transaction, 'amount'); + const destAddress = this.safeValue (transaction, 'destAddress', {}); + const address = this.safeString (destAddress, 'address'); + const tag = this.safeString (destAddress, 'destTag'); + const txid = this.safeString (transaction, 'networkTransactionId'); + const type = this.safeString (transaction, 'transactionType'); + const timestamp = this.safeInteger (transaction, 'time'); + const currencyId = this.safeString (transaction, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); + const feeCost = this.safeNumber (transaction, 'commission'); + return { + 'info': transaction, + 'id': id, + 'currency': code, + 'amount': amount, + 'address': address, + 'addressTo': address, + 'addressFrom': undefined, + 'tag': tag, + 'tagTo': tag, + 'tagFrom': undefined, + 'status': status, + 'type': type, + 'updated': undefined, + 'txid': txid, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'fee': { + 'currency': code, + 'cost': feeCost, + }, + }; + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let url = ''; + let query = params; + const accountCategory = (api === 'accountCategory'); + if (accountCategory || (api === 'accountGroup')) { + url += this.implodeParams ('/{account-group}', params); + query = this.omit (params, 'account-group'); + } + const request = this.implodeParams (path, query); + url += '/api/pro/' + this.version; + if (accountCategory) { + url += this.implodeParams ('/{account-category}', query); + query = this.omit (query, 'account-category'); + } + url += '/' + request; + query = this.omit (query, this.extractParams (path)); + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const timestamp = this.milliseconds ().toString (); + const payload = timestamp + '+' + request; + const hmac = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64'); + headers = { + 'x-auth-key': this.apiKey, + 'x-auth-timestamp': timestamp, + 'x-auth-signature': hmac, + }; + if (method === 'GET') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + headers['Content-Type'] = 'application/json'; + body = this.json (query); + } + } + url = this.urls['api'] + url; + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; // fallback to default error handler + } + // + // {'code': 6010, 'message': 'Not enough balance.'} + // {'code': 60060, 'message': 'The order is already filled or canceled.'} + // {"code":2100,"message":"ApiKeyFailure"} + // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}} + // + const code = this.safeString (response, 'code'); + const message = this.safeString (response, 'message'); + const error = (code !== undefined) && (code !== '0'); + if (error || (message !== undefined)) { + const feedback = this.id + ' ' + body; + this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); + this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); + this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); + throw new ExchangeError (feedback); // unknown message + } + } +}; + +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],6:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -3608,6 +4837,7 @@ const { // eslint-disable-line object-curly-newline const { TRUNCATE, ROUND, DECIMAL_PLACES, NO_PADDING } = functions.precisionConstants const BN = require ('../static_dependencies/BN/bn') +const Precise = require ('./Precise') // ---------------------------------------------------------------------------- @@ -3788,6 +5018,11 @@ module.exports = class Exchange { this.minFundingAddressLength = 1 // used in checkAddress this.substituteCommonCurrencyCodes = true // reserved + this.quoteJsonNumbers = true // treat numbers in json as quoted precise strings + this.number = Number // or String (a pointer to a function) + + // whether fees should be summed by currency code + this.reduceFees = true // do not delete this line, it is needed for users to be able to define their own fetchImplementation this.fetchImplementation = defaultFetch @@ -4083,7 +5318,7 @@ module.exports = class Exchange { parseJson (jsonString) { try { if (this.isJsonEncodedObject (jsonString)) { - return JSON.parse (jsonString) + return JSON.parse (this.onJsonResponse (jsonString)) } } catch (e) { // SyntaxError @@ -4162,7 +5397,11 @@ module.exports = class Exchange { } onRestResponse (statusCode, statusText, url, method, responseHeaders, responseBody, requestHeaders, requestBody) { - return responseBody.trim ().replace (/:(\d{15,}),/g, ':"$1",'); + return responseBody.trim () + } + + onJsonResponse (responseBody) { + return this.quoteJsonNumbers ? responseBody.replace (/":([+.0-9eE-]+),/g, '":"$1",') : responseBody; } setMarkets (markets, currencies = undefined) { @@ -4482,8 +5721,8 @@ module.exports = class Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = parseFloat (bidask[priceKey]) - const amount = parseFloat (bidask[amountKey]) + const price = this.safeNumber (bidask, priceKey) + const amount = this.safeNumber (bidask, amountKey) return [ price, amount ] } @@ -4509,7 +5748,7 @@ module.exports = class Exchange { } } - parseBalance (balance) { + parseBalance (balance, legacy = true) { const codes = Object.keys (this.omit (balance, [ 'info', 'free', 'used', 'total' ])); @@ -4521,20 +5760,34 @@ module.exports = class Exchange { const code = codes[i] if (balance[code].total === undefined) { if (balance[code].free !== undefined && balance[code].used !== undefined) { - balance[code].total = this.sum (balance[code].free, balance[code].used) + if (legacy) { + balance[code].total = this.sum (balance[code].free, balance[code].used) + } else { + balance[code].total = Precise.stringAdd (balance[code].free, balance[code].used) + } } } if (balance[code].free === undefined) { if (balance[code].total !== undefined && balance[code].used !== undefined) { - balance[code].free = this.sum (balance[code].total, -balance[code].used) + if (legacy) { + balance[code].free = this.sum (balance[code].total, -balance[code].used) + } else { + balance[code].free = Precise.stringSub (balance[code].total, balance[code].used) + } } } if (balance[code].used === undefined) { if (balance[code].total !== undefined && balance[code].free !== undefined) { - balance[code].used = this.sum (balance[code].total, -balance[code].free) + if (legacy) { + balance[code].used = this.sum (balance[code].total, -balance[code].free) + } else { + balance[code].used = Precise.stringSub (balance[code].total, balance[code].free) + } } } - + balance[code].free = this.parseNumber (balance[code].free) + balance[code].used = this.parseNumber (balance[code].used) + balance[code].total = this.parseNumber (balance[code].total) balance.free[code] = balance[code].free balance.used[code] = balance[code].used balance.total[code] = balance[code].total @@ -4543,6 +5796,10 @@ module.exports = class Exchange { return balance } + async fetchBalance (params = {}) { + throw new NotSupported (this.id + ' fetchBalance not supported yet') + } + async fetchPartialBalance (part, params = {}) { const balance = await this.fetchBalance (params) return balance[part] @@ -4652,11 +5909,27 @@ module.exports = class Exchange { return indexed ? indexBy (result, key) : result } + parseTickers (tickers, symbols = undefined) { + const result = []; + for (let i = 0; i < tickers.length; i++) { + result.push (this.parseTicker (tickers[i])); + } + return this.filterByArray (result, 'symbol', symbols); + } + + parseDepositAddresses (addresses, codes = undefined) { + let result = []; + for (let i = 0; i < addresses.length; i++) { + const address = this.parseDepositAddress (addresses[i]); + result.push (address); + } + if (codes) { + result = this.filterByArray (result, 'currency', codes); + } + return this.indexBy (result, 'currency'); + } + parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (trades)) { - // throw new ExchangeError (this.id + ' parseTrades expected an array in the trades argument, but got ' + typeof trades); - // } let result = Object.values (trades || []).map ((trade) => this.extend (this.parseTrade (trade, market), params)) result = sortBy (result, 'timestamp') const symbol = (market !== undefined) ? market['symbol'] : undefined @@ -4665,10 +5938,6 @@ module.exports = class Exchange { } parseTransactions (transactions, currency = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (transactions)) { - // throw new ExchangeError (this.id + ' parseTransactions expected an array in the transactions argument, but got ' + typeof transactions); - // } let result = Object.values (transactions || []).map ((transaction) => this.extend (this.parseTransaction (transaction, currency), params)) result = this.sortBy (result, 'timestamp'); const code = (currency !== undefined) ? currency['code'] : undefined; @@ -4676,6 +5945,14 @@ module.exports = class Exchange { return this.filterByCurrencySinceLimit (result, code, since, limit, tail); } + parseTransfers (transfers, currency = undefined, since = undefined, limit = undefined, params = {}) { + let result = Object.values (transfers || []).map ((transfer) => this.extend (this.parseTransfer (transfer, currency), params)) + result = this.sortBy (result, 'timestamp'); + const code = (currency !== undefined) ? currency['code'] : undefined; + const tail = since === undefined; + return this.filterByCurrencySinceLimit (result, code, since, limit, tail); + } + parseLedger (data, currency = undefined, since = undefined, limit = undefined, params = {}) { let result = []; const array = Object.values (data || []); @@ -4820,19 +6097,19 @@ module.exports = class Exchange { return this.createOrder (symbol, ...args) } - createLimitOrder (symbol, side, amount, price = undefined, params = {}) { + createLimitOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'limit', side, amount, price, params) } - createMarketOrder (symbol, side, amount, price = undefined, params = {}) { + createMarketOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'market', side, amount, price, params) } - createLimitBuyOrder (symbol, amount, price = undefined, params = {}) { + createLimitBuyOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'buy', amount, price, params) } - createLimitSellOrder (symbol, amount, price = undefined, params = {}) { + createLimitSellOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'sell', amount, price, params) } @@ -4865,15 +6142,43 @@ module.exports = class Exchange { } calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol] - const rate = market[takerOrMaker] - const cost = parseFloat (this.costToPrecision (symbol, amount * price)) + const market = this.markets[symbol]; + const feeSide = this.safeString (market, 'feeSide', 'quote'); + let key = 'quote'; + let cost = undefined; + if (feeSide === 'quote') { + // the fee is always in quote currency + cost = amount * price; + } else if (feeSide === 'base') { + // the fee is always in base currency + cost = amount; + } else if (feeSide === 'get') { + // the fee is always in the currency you get + cost = amount; + if (side === 'sell') { + cost *= price; + } else { + key = 'base'; + } + } else if (feeSide === 'give') { + // the fee is always in the currency you give + cost = amount; + if (side === 'buy') { + cost *= price; + } else { + key = 'base'; + } + } + const rate = market[takerOrMaker]; + if (cost !== undefined) { + cost *= rate; + } return { 'type': takerOrMaker, - 'currency': market['quote'], + 'currency': market[key], 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, rate * cost)), - } + 'cost': cost, + }; } checkRequiredDependencies () { @@ -4957,6 +6262,25 @@ module.exports = class Exchange { return new BN (a).pow (new BN (b)) } + reduceFeesByCurrency (fees) { + const reduced = {}; + for (let i = 0; i < fees.length; i++) { + const fee = fees[i]; + const feeCurrencyCode = this.safeValue (fee, 'currency'); + if (feeCurrencyCode !== undefined) { + if (feeCurrencyCode in reduced) { + reduced[feeCurrencyCode]['cost'] = this.sum (reduced[feeCurrencyCode]['cost'], fee['cost']); + } else { + reduced[feeCurrencyCode] = { + 'cost': fee['cost'], + 'currency': feeCurrencyCode, + }; + } + } + } + return Object.values (reduced); + } + safeOrder (order) { // Cost // Remaining @@ -4965,70 +6289,295 @@ module.exports = class Exchange { // Amount // Filled // - // First we try to calculate filled from the trades - const parseFilled = order['filled'] === undefined; - const parseCost = order['cost'] === undefined; - if (parseFilled) { - order['filled'] = 0 - } - if (parseCost) { - order['cost'] = 0 - } - if (parseFilled || parseCost) { - if (Array.isArray (order['trades'])) { - for (let i = 0; i < order['trades'].length; i++) { - const trade = order['trades'][i] - if (parseFilled) { - order['filled'] = this.sum (order['filled'], trade['amount']) + // first we try to calculate the order fields from the trades + let amount = this.safeValue (order, 'amount'); + let remaining = this.safeValue (order, 'remaining'); + let filled = this.safeValue (order, 'filled'); + let cost = this.safeValue (order, 'cost'); + let average = this.safeValue (order, 'average'); + let price = this.safeValue (order, 'price'); + let lastTradeTimeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); + const parseFilled = (filled === undefined); + const parseCost = (cost === undefined); + const parseLastTradeTimeTimestamp = (lastTradeTimeTimestamp === undefined); + const parseFee = this.safeValue (order, 'fee') === undefined; + const parseFees = this.safeValue (order, 'fees') === undefined; + const shouldParseFees = parseFee || parseFees; + const fees = shouldParseFees ? [] : undefined; + if (parseFilled || parseCost || shouldParseFees) { + const trades = this.safeValue (order, 'trades'); + if (trades !== undefined) { + if (parseFilled) { + filled = 0; + } + if (parseCost) { + cost = 0; + } + for (let i = 0; i < trades.length; i++) { + const trade = trades[i]; + const tradeAmount = this.safeValue (trade, 'amount'); + if (parseFilled && (tradeAmount !== undefined)) { + filled = this.sum (filled, tradeAmount); } - if (parseCost) { - order['cost'] = this.sum (order['cost'], trade['cost']) + const tradeCost = this.safeValue (trade, 'cost'); + if (parseCost && (tradeCost !== undefined)) { + cost = this.sum (cost, tradeCost); + } + const tradeTimestamp = this.safeValue (trade, 'timestamp'); + if (parseLastTradeTimeTimestamp && (tradeTimestamp !== undefined)) { + if (lastTradeTimeTimestamp === undefined) { + lastTradeTimeTimestamp = tradeTimestamp; + } else { + lastTradeTimeTimestamp = Math.max (lastTradeTimeTimestamp, tradeTimestamp); + } + } + if (shouldParseFees) { + const tradeFees = this.safeValue (trade, 'fees'); + if (tradeFees !== undefined) { + for (let j = 0; j < tradeFees.length; j++) { + const tradeFee = tradeFees[j]; + fees.push (this.extend ({}, tradeFee)); + } + } else { + const tradeFee = this.safeValue (trade, 'fee'); + if (tradeFee !== undefined) { + fees.push (this.extend ({}, tradeFee)); + } + } } } } } - // We ensure amount = filled + remaining - if (order['amount'] === undefined) { - if (order['filled'] !== undefined && order['remaining'] !== undefined) { - order['amount'] = this.sum (order['filled'], order['remaining']) + if (shouldParseFees) { + const reducedFees = this.reduceFees ? this.reduceFeesByCurrency (fees) : fees; + const reducedLength = reducedFees.length; + if (!parseFee && (reducedLength === 0)) { + reducedFees.push (order['fee']); + } + if (parseFees) { + order['fees'] = reducedFees; + } + if (parseFee && (reducedLength === 1)) { + order['fee'] = reducedFees[0]; } } - if (order['filled'] === undefined) { - if (order['amount'] !== undefined && order['remaining'] !== undefined) { - order['filled'] = Math.max (this.sum (order['amount'], -order['remaining']), 0) + if (amount === undefined) { + // ensure amount = filled + remaining + if (filled !== undefined && remaining !== undefined) { + amount = this.sum (filled, remaining); + } else if (this.safeString (order, 'status') === 'closed') { + amount = filled; } } - if (order['remaining'] === undefined) { - if (order['amount'] !== undefined && order['filled'] !== undefined) { - order['remaining'] = Math.max (this.sum (order['amount'], -order['filled']), 0) + if (filled === undefined) { + if (amount !== undefined && remaining !== undefined) { + filled = Math.max (this.sum (amount, -remaining), 0); } } - // We ensure that the average field is calculated correctly - if (order['average'] === undefined) { - if (order['filled'] !== undefined && order['cost'] !== undefined && order['cost'] > 0) { - order['average'] = order['filled'] / order['cost'] + if (remaining === undefined) { + if (amount !== undefined && filled !== undefined) { + remaining = Math.max (this.sum (amount, -filled), 0); } } - // We also ensure the cost field is calculated correctly - const costPriceExists = (order['average'] !== undefined) || (order['price'] !== undefined) - if ((order['filled'] !== undefined) && costPriceExists) { - let costPrice = undefined; - if (order['average'] === undefined) { - costPrice = order['price'] - } else { - costPrice = order['average'] + // ensure that the average field is calculated correctly + if (average === undefined) { + if ((filled !== undefined) && (cost !== undefined) && (cost > 0)) { + average = cost / filled; } - order['cost'] = costPrice * order['filled'] } - // We add support for market orders - if (order['price'] === undefined && order['type'] === 'market') { - order['price'] = order['average'] + // also ensure the cost field is calculated correctly + const costPriceExists = (average !== undefined) || (price !== undefined); + if (parseCost && (filled !== undefined) && costPriceExists) { + cost = (average === undefined) ? (price * filled) : (average * filled); } - return order + // support for market orders + const orderType = this.safeValue (order, 'type'); + const emptyPrice = (price === undefined) || (price === 0.0); + if (emptyPrice && (orderType === 'market')) { + price = average; + } + return this.extend (order, { + 'lastTradeTimestamp': lastTradeTimeTimestamp, + 'price': price, + 'amount': amount, + 'cost': cost, + 'average': average, + 'filled': filled, + 'remaining': remaining, + }); + } + + parseNumber (value, d = undefined) { + if (value === undefined) { + return d + } else { + try { + return this.number (value) + } catch (e) { + return d + } + } + } + + safeNumber (object, key, d = undefined) { + const value = this.safeString (object, key) + return this.parseNumber (value, d) + } + + safeNumber2 (object, key1, key2, d = undefined) { + const value = this.safeString2 (object, key1, key2) + return this.parseNumber (value, d) } } -},{"../static_dependencies/BN/bn":126,"./errors":8,"./functions":9}],7:[function(require,module,exports){ +},{"../static_dependencies/BN/bn":123,"./Precise":7,"./errors":9,"./functions":10}],7:[function(require,module,exports){ +'use strict' + +const BN = require ('../static_dependencies/BN/bn') + +class Precise { + constructor (number, decimals = 0) { + const isBN = number instanceof BN + const isString = typeof number === 'string' + if (!(isBN || isString)) { + throw new Error ('Precise initiated with something other than a string or BN') + } + if (isBN) { + this.integer = number + this.decimals = decimals + } else { + if (decimals) { + throw new Error ('Cannot set decimals when initializing with a string') + } + let modifier = 0 + number = number.toLowerCase () + if (number.indexOf ('e') > -1) { + [ number, modifier ] = number.split ('e') + modifier = parseInt (modifier) + } + const decimalIndex = number.indexOf ('.') + this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0 + const integerString = number.replace ('.', '') + this.integer = new BN (integerString) + this.decimals = this.decimals - modifier + } + this.base = 10 + this.reduce () + } + + mul (other) { + // other must be another instance of Precise + const integerResult = this.integer.mul (other.integer) + return new Precise (integerResult, this.decimals + other.decimals) + } + + div (other, precision = 18) { + const distance = precision - this.decimals + other.decimals + let numerator + if (distance === 0) { + numerator = this.integer + } else if (distance < 0) { + const exponent = new BN (this.base).pow (new BN (-distance)) + numerator = this.integer.div (exponent) + } else { + const exponent = new BN (this.base).pow (new BN (distance)) + numerator = this.integer.mul (exponent) + } + const result = numerator.div (other.integer) + return new Precise (result, precision) + } + + add (other) { + if (this.decimals === other.decimals) { + const integerResult = this.integer.add (other.integer) + return new Precise (integerResult, this.decimals) + } else { + const [ smaller, bigger ] = + (this.decimals > other.decimals) ? [ other, this ] : [ this, other ] + const exponent = new BN (bigger.decimals - smaller.decimals) + const normalised = smaller.integer.mul (new BN (this.base).pow (exponent)) + const result = normalised.add (bigger.integer) + return new Precise (result, bigger.decimals) + } + } + + sub (other) { + const negative = new Precise (other.integer.neg (), other.decimals) + return this.add (negative) + } + + reduce () { + const zero = new BN (0) + if (this.integer.eq (zero)) { + this.decimals = 0 + return this + } + const base = new BN (this.base) + let divmod = this.integer.divmod (base) + while (divmod.mod.eq (zero)) { + this.integer = divmod.div + this.decimals-- + divmod = this.integer.divmod (base) + } + return this + } + + toString () { + const sign = this.integer.negative ? '-' : '' + const integerArray = Array.from (this.integer.abs ().toString (this.base).padStart (this.decimals, '0')) + const index = integerArray.length - this.decimals + let item + if (index === 0) { + // if we are adding to the front + item = '0.' + } else if (this.decimals < 0) { + item = '0'.repeat (-this.decimals) + } else if (this.decimals === 0) { + item = '' + } else { + item = '.' + } + integerArray.splice (index, 0, item) + return sign + integerArray.join ('') + } + + static stringMul (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).mul (new Precise (string2)).toString () + } + + static stringDiv (string1, string2, precision = 18) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).div (new Precise (string2), precision).toString () + } + + static stringAdd (string1, string2) { + if ((string1 === undefined) && (string2 === undefined)) { + return undefined + } + if (string1 === undefined) { + return string2 + } else if (string2 === undefined) { + return string1 + } + return (new Precise (string1)).add (new Precise (string2)).toString () + } + + static stringSub (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).sub (new Precise (string2)).toString () + } +} + +module.exports = Precise; + +},{"../static_dependencies/BN/bn":123}],8:[function(require,module,exports){ 'use strict'; const errorHierarchy = { @@ -5074,7 +6623,7 @@ const errorHierarchy = { module.exports = errorHierarchy; -},{}],8:[function(require,module,exports){ +},{}],9:[function(require,module,exports){ 'use strict'; const errorHierarchy = require ('./errorHierarchy.js') @@ -5131,7 +6680,7 @@ module.exports = subclass ( errorHierarchy ) -},{"./errorHierarchy.js":7}],9:[function(require,module,exports){ +},{"./errorHierarchy.js":8}],10:[function(require,module,exports){ 'use strict'; /* ------------------------------------------------------------------------ */ @@ -5161,7 +6710,7 @@ module.exports = unCamelCasePropertyNames (Object.assign ({} /* ------------------------------------------------------------------------ */ -},{"./functions/crypto":10,"./functions/encode":11,"./functions/generic":12,"./functions/misc":13,"./functions/number":14,"./functions/platform":15,"./functions/string":16,"./functions/throttle":17,"./functions/time":18,"./functions/type":19}],10:[function(require,module,exports){ +},{"./functions/crypto":11,"./functions/encode":12,"./functions/generic":13,"./functions/misc":14,"./functions/number":15,"./functions/platform":16,"./functions/string":17,"./functions/throttle":18,"./functions/time":19,"./functions/type":20}],11:[function(require,module,exports){ 'use strict' /* ------------------------------------------------------------------------ */ @@ -5321,7 +6870,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"../../static_dependencies/BN/bn.js":126,"../../static_dependencies/crypto-js/crypto-js":127,"./../../static_dependencies/elliptic/lib/elliptic":128,"./../../static_dependencies/node-rsa/NodeRSA":146,"./../errors":8,"./encode":11,"./string":16}],11:[function(require,module,exports){ +},{"../../static_dependencies/BN/bn.js":123,"../../static_dependencies/crypto-js/crypto-js":124,"./../../static_dependencies/elliptic/lib/elliptic":125,"./../../static_dependencies/node-rsa/NodeRSA":143,"./../errors":9,"./encode":12,"./string":17}],12:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -5343,7 +6892,6 @@ let base58Encoder = null module.exports = { json: (data, params = undefined) => JSON.stringify (data) - , unjson: JSON.parse , isJsonEncodedObject: object => ( (typeof object === 'string') && @@ -5441,7 +6989,7 @@ module.exports['byteArrayToWordArray'] = byteArrayToWordArray /* ------------------------------------------------------------------------ */ -},{"../../static_dependencies/BN/bn":126,"../../static_dependencies/crypto-js/crypto-js":127,"../../static_dependencies/qs/index":162}],12:[function(require,module,exports){ +},{"../../static_dependencies/BN/bn":123,"../../static_dependencies/crypto-js/crypto-js":124,"../../static_dependencies/qs/index":159}],13:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -5679,7 +7227,7 @@ module.exports = { } -},{"./type":19}],13:[function(require,module,exports){ +},{"./type":20}],14:[function(require,module,exports){ 'use strict'; const { ROUND_UP, ROUND_DOWN } = require ('./number') @@ -5819,7 +7367,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"../errors":8,"./number":14}],14:[function(require,module,exports){ +},{"../errors":9,"./number":15}],15:[function(require,module,exports){ 'use strict' /* ------------------------------------------------------------------------ @@ -6160,7 +7708,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{}],15:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ (function (process){ "use strict"; @@ -6201,7 +7749,7 @@ module.exports = { defaultFetch, } }).call(this,require('_process')) -},{"../../static_dependencies/fetch-ponyfill/fetch-node":144,"_process":210}],16:[function(require,module,exports){ +},{"../../static_dependencies/fetch-ponyfill/fetch-node":141,"_process":206}],17:[function(require,module,exports){ "use strict"; // ---------------------------------------------------------------------------- @@ -6221,7 +7769,7 @@ module.exports = { , strip: s => s.replace(/^\s+|\s+$/g, '') } -},{}],17:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -6287,7 +7835,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{"./time":18}],18:[function(require,module,exports){ +},{"./time":19}],19:[function(require,module,exports){ 'use strict'; /* ------------------------------------------------------------------------ */ @@ -6491,7 +8039,7 @@ module.exports = /* ------------------------------------------------------------------------ */ -},{}],19:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ "use strict"; /* ------------------------------------------------------------------------ */ @@ -6559,7 +8107,7 @@ module.exports = { /* ------------------------------------------------------------------------ */ -},{}],20:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -6593,13 +8141,14 @@ module.exports = class bequant extends hitbtc { } }; -},{"./hitbtc":93}],21:[function(require,module,exports){ +},{"./hitbtc":91}],22:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AccountSuspended, ArgumentsRequired, AuthenticationError, DDoSProtection, ExchangeNotAvailable, InvalidOrder, OrderNotFound, PermissionDenied, InsufficientFunds, BadSymbol, RateLimitExceeded, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -6825,9 +8374,9 @@ module.exports = class bibox extends Exchange { const quote = this.safeCurrencyCode (quoteId); symbol = base + '/' + quote; } - const last = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); - const baseVolume = this.safeFloat2 (ticker, 'vol', 'vol24H'); + const last = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); + const baseVolume = this.safeNumber2 (ticker, 'vol', 'vol24H'); let open = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; @@ -6841,11 +8390,11 @@ module.exports = class bibox extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -6856,7 +8405,7 @@ module.exports = class bibox extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': baseVolume, - 'quoteVolume': this.safeFloat (ticker, 'amount'), + 'quoteVolume': this.safeNumber (ticker, 'amount'), 'info': ticker, }; } @@ -6872,17 +8421,6 @@ module.exports = class bibox extends Exchange { return this.parseTicker (response['result'], market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - const ticker = this.parseTicker (rawTickers[i]); - if ((symbols === undefined) || (this.inArray (ticker['symbol'], symbols))) { - tickers.push (ticker); - } - } - return tickers; - } - async fetchTickers (symbols = undefined, params = {}) { const request = { 'cmd': 'marketAll', @@ -6915,7 +8453,7 @@ module.exports = class bibox extends Exchange { symbol = market['symbol']; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = this.safeString (trade, 'fee_symbol'); if (feeCurrency !== undefined) { if (feeCurrency in this.currencies_by_id) { @@ -6925,12 +8463,11 @@ module.exports = class bibox extends Exchange { } } const feeRate = undefined; // todo: deduce from market if market is defined - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if (feeCost !== undefined) { fee = { 'cost': -feeCost, @@ -6981,7 +8518,7 @@ module.exports = class bibox extends Exchange { request['size'] = limit; // default = 200 } const response = await this.publicGetMdata (this.extend (request, params)); - return this.parseOrderBook (response['result'], this.safeFloat (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); + return this.parseOrderBook (response['result'], this.safeNumber (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); } parseOHLCV (ohlcv, market = undefined) { @@ -6997,11 +8534,11 @@ module.exports = class bibox extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -7093,7 +8630,7 @@ module.exports = class bibox extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw_min'), + 'min': this.safeNumber (currency, 'withdraw_min'), 'max': undefined, }, }, @@ -7225,19 +8762,17 @@ module.exports = class bibox extends Exchange { code = this.currencies_by_id[code]['code']; } const account = this.account (); - let balance = indexed[id]; + const balance = indexed[id]; if (typeof balance === 'string') { - balance = parseFloat (balance); account['free'] = balance; - account['used'] = 0.0; account['total'] = balance; } else { - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -7328,8 +8863,8 @@ module.exports = class bibox extends Exchange { let tag = this.safeString (transaction, 'addr_remark'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'fee'); if (type === 'deposit') { feeCost = 0; tag = undefined; @@ -7437,26 +8972,19 @@ module.exports = class bibox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const type = (order['order_type'] === 1) ? 'market' : 'limit'; - const timestamp = order['createdAt']; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'deal_price'); - const filled = this.safeFloat (order, 'deal_amount'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat2 (order, 'deal_money', 'money'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - cost = price * filled; - } - } - const side = (order['order_side'] === 1) ? 'buy' : 'sell'; + const rawType = this.safeString (order, 'order_type'); + const type = (rawType === '1') ? 'market' : 'limit'; + const timestamp = this.safeInteger (order, 'createdAt'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'deal_price'); + const filled = this.safeNumber (order, 'deal_amount'); + const amount = this.safeNumber (order, 'amount'); + const cost = this.safeNumber2 (order, 'deal_money', 'money'); + const rawSide = this.safeString (order, 'order_side'); + const side = (rawSide === '1') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -7464,8 +8992,7 @@ module.exports = class bibox extends Exchange { 'currency': undefined, }; } - cost = cost ? cost : (parseFloat (price) * filled); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -7483,11 +9010,11 @@ module.exports = class bibox extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -7655,7 +9182,7 @@ module.exports = class bibox extends Exchange { }; const response = await this.privatePostTransfer (request); info[code] = response; - withdrawFees[code] = this.safeFloat (response['result'], 'withdraw_fee'); + withdrawFees[code] = this.safeNumber (response['result'], 'withdraw_fee'); } return { 'info': info, @@ -7725,13 +9252,14 @@ module.exports = class bibox extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],22:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],23:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, OrderNotFound, InsufficientFunds, PermissionDenied, BadRequest, RateLimitExceeded, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -7988,28 +9516,28 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (ticker, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = undefined; - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', {}); const ask = this.safeValue (ticker, 'ask', {}); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 'price'), - 'bidVolume': this.safeFloat (bid, 'quantity'), - 'ask': this.safeFloat (ask, 'price'), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 'price'), + 'bidVolume': this.safeNumber (bid, 'quantity'), + 'ask': this.safeNumber (ask, 'price'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, 'last': close, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'daily_change'), + 'change': this.safeNumber (ticker, 'daily_change'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -8174,16 +9702,13 @@ module.exports = class bigone extends Exchange { // } // const timestamp = this.parse8601 (this.safeString2 (trade, 'created_at', 'inserted_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } let side = this.safeString (trade, 'side'); const takerSide = this.safeString (trade, 'taker_side'); let takerOrMaker = undefined; @@ -8257,8 +9782,8 @@ module.exports = class bigone extends Exchange { takerCurrencyCode = market['quote']; } } - const makerFeeCost = this.safeFloat (trade, 'maker_fee'); - const takerFeeCost = this.safeFloat (trade, 'taker_fee'); + const makerFeeCost = this.safeNumber (trade, 'maker_fee'); + const takerFeeCost = this.safeNumber (trade, 'taker_fee'); if (makerFeeCost !== undefined) { if (takerFeeCost !== undefined) { result['fees'] = [ @@ -8321,11 +9846,11 @@ module.exports = class bigone extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -8396,11 +9921,11 @@ module.exports = class bigone extends Exchange { const symbol = this.safeString (balance, 'asset_symbol'); const code = this.safeCurrencyCode (symbol); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -8422,13 +9947,9 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (order, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (amount !== undefined && filled !== undefined) { - remaining = Math.max (0, amount - filled); - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); const status = this.parseOrderStatus (this.safeString (order, 'state')); let side = this.safeString (order, 'side'); if (side === 'BID') { @@ -8436,15 +9957,9 @@ module.exports = class bigone extends Exchange { } else { side = 'sell'; } - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'updated_at')); - const average = this.safeFloat (order, 'avg_deal_price'); - return { + const average = this.safeNumber (order, 'avg_deal_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -8459,14 +9974,14 @@ module.exports = class bigone extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -8490,7 +10005,7 @@ module.exports = class bigone extends Exchange { const isStopLimit = (uppercaseType === 'STOP_LIMIT'); const isStopMarket = (uppercaseType === 'STOP_MARKET'); if (isStopLimit || isStopMarket) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price parameter'); } @@ -8829,7 +10344,7 @@ module.exports = class bigone extends Exchange { const currencyId = this.safeString (transaction, 'asset_symbol'); const code = this.safeCurrencyCode (currencyId); const id = this.safeInteger (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const timestamp = this.parse8601 (this.safeString (transaction, 'inserted_at')); const updated = this.parse8601 (this.safeString2 (transaction, 'updated_at', 'completed_at')); @@ -9000,14 +10515,15 @@ module.exports = class bigone extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],23:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],24:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, RateLimitExceeded, PermissionDenied, NotSupported, BadRequest, BadSymbol, AccountSuspended, OrderImmediatelyFillable } = require ('./base/errors'); -const { ROUND, TRUNCATE } = require ('./base/functions/number'); +const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -9050,6 +10566,8 @@ module.exports = class binance extends Exchange { 'fetchTransactions': false, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, + 'fetchTransfers': true, }, 'timeframes': { '1m': '1m', @@ -9198,6 +10716,26 @@ module.exports = class binance extends Exchange { 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/recentRecord', 'apiReferral/kickback/historicalRecord', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccount', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/info', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/recentRecord', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/status', + 'broker/subAccount/depositHist', + 'broker/subAccount/spotSummary', + 'broker/subAccount/marginSummary', + 'broker/subAccount/futuresSummary', + 'broker/rebate/futures/recentRecord', + 'broker/subAccountApi/ipRestriction', + 'broker/universalTransfer', + // v2 not supported yet + // GET /sapi/v2/broker/subAccount/futuresSummary ], 'post': [ 'asset/dust', @@ -9237,11 +10775,30 @@ module.exports = class binance extends Exchange { // leveraged token endpoints 'blvt/subscribe', 'blvt/redeem', - // broker api + // brokerage API 'apiReferral/customization', 'apiReferral/userCustomization', 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/historicalRecord', + 'broker/subAccount', + 'broker/subAccount/margin', + 'broker/subAccount/futures', + 'broker/subAccountApi', + 'broker/subAccountApi/permission', + 'broker/subAccountApi/commission', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/spot', + 'broker/subAccount/bnbBurn/marginInterest', + 'broker/subAccount/blvt', + 'broker/subAccountApi/ipRestriction', + 'broker/subAccountApi/ipRestriction/ipList', + 'broker/universalTransfer', + 'broker/subAccountApi/permission/universalTransfer', + 'broker/subAccountApi/permission/vanillaOptions', ], 'put': [ 'userDataStream', @@ -9252,6 +10809,9 @@ module.exports = class binance extends Exchange { 'margin/order', 'userDataStream', 'userDataStream/isolated', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccountApi/ipRestriction/ipList', ], }, 'wapi': { @@ -9388,6 +10948,8 @@ module.exports = class binance extends Exchange { 'positionSide/dual', 'userTrades', 'income', + 'commissionRate', + 'apiTradingStatus', // broker endpoints 'apiReferral/ifNewUser', 'apiReferral/customization', @@ -9477,6 +11039,7 @@ module.exports = class binance extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.001, @@ -9501,7 +11064,7 @@ module.exports = class binance extends Exchange { 'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision 'newOrderRespType': { 'market': 'FULL', // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills - 'limit': 'RESULT', // we change it from 'ACK' by default to 'RESULT' + 'limit': 'FULL', // we change it from 'ACK' by default to 'FULL' (returns immediately if limit is not hit) }, 'quoteOrderQty': true, // whether market orders support amounts in quote currency 'broker': { @@ -9510,6 +11073,25 @@ module.exports = class binance extends Exchange { 'future': 'x-xcKtGhcu', 'delivery': 'x-xcKtGhcu', }, + 'fetchPositions': { + 'future': 'fapiPrivateV2GetAccount', // 'fapiPrivateGetPositionRisk' + 'delivery': 'dapiPrivateGetAccount', // 'dapiPrivateGetPositionRisk' + }, + 'accountsByType': { + 'main': 'MAIN', + 'spot': 'MAIN', + 'margin': 'MARGIN', + 'future': 'UMFUTURE', + 'delivery': 'CMFUTURE', + 'mining': 'MINING', + }, + 'typesByAccount': { + 'MAIN': 'spot', + 'MARGIN': 'margin', + 'UMFUTURE': 'future', + 'CMFUTURE': 'delivery', + 'MINING': 'mining', + }, }, // https://binance-docs.github.io/apidocs/spot/en/#error-codes-2 'exceptions': { @@ -9567,6 +11149,8 @@ module.exports = class binance extends Exchange { '-3010': ExchangeError, // {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."} '-3022': AccountSuspended, // You account's trading is banned. '-4028': BadRequest, // {"code":-4028,"msg":"Leverage 100 is not valid"} + '-3020': InsufficientFunds, // {"code":-3020,"msg":"Transfer out amount exceeds max amount."} + '-3041': InsufficientFunds, // {"code":-3041,"msg":"Balance is not enough"} '-5013': InsufficientFunds, // Asset transfer failed: insufficient balance" }, }); @@ -9709,13 +11293,14 @@ module.exports = class binance extends Exchange { let fee = undefined; for (let j = 0; j < networkList.length; j++) { const networkItem = networkList[j]; - const name = this.safeString (networkItem, 'name'); - const withdrawFee = this.safeFloat (networkItem, 'withdrawFee'); + const network = this.safeString (networkItem, 'network'); + // const name = this.safeString (networkItem, 'name'); + const withdrawFee = this.safeNumber (networkItem, 'withdrawFee'); const depositEnable = this.safeValue (networkItem, 'depositEnable'); const withdrawEnable = this.safeValue (networkItem, 'withdrawEnable'); isDepositEnabled = isDepositEnabled || depositEnable; isWithdrawEnabled = isWithdrawEnabled || withdrawEnable; - fees[name] = withdrawFee; + fees[network] = withdrawFee; const isDefault = this.safeValue (networkItem, 'isDefault'); if (isDefault || fee === undefined) { fee = withdrawFee; @@ -9901,7 +11486,7 @@ module.exports = class binance extends Exchange { if (this.options['adjustForTimeDifference']) { await this.loadTimeDifference (); } - const markets = this.safeValue (response, 'symbols'); + const markets = this.safeValue (response, 'symbols', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -9966,10 +11551,10 @@ module.exports = class binance extends Exchange { // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } @@ -9980,47 +11565,26 @@ module.exports = class binance extends Exchange { const stepSize = this.safeString (filter, 'stepSize'); entry['precision']['amount'] = this.precisionFromString (stepSize); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat2 (filter, 'minNotional', 'notional'); + entry['limits']['cost']['min'] = this.safeNumber2 (filter, 'minNotional', 'notional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot'); @@ -10191,8 +11755,8 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -10205,13 +11769,13 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['used'] = this.safeFloat (balance, 'initialMargin'); - account['total'] = this.safeFloat2 (balance, 'marginBalance', 'balance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['used'] = this.safeString (balance, 'initialMargin'); + account['total'] = this.safeString2 (balance, 'marginBalance', 'balance'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -10264,36 +11828,36 @@ module.exports = class binance extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'openPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'openPrice'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } async fetchStatus (params = {}) { const response = await this.wapiGetSystemStatus (params); - let status = this.safeValue (response, 'status'); + let status = this.safeString (response, 'status'); if (status !== undefined) { - status = (status === 0) ? 'ok' : 'maintenance'; + status = (status === '0') ? 'ok' : 'maintenance'; this.status = this.extend (this.status, { 'status': status, 'updated': this.milliseconds (), @@ -10322,14 +11886,6 @@ module.exports = class binance extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot'); @@ -10384,11 +11940,11 @@ module.exports = class binance extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -10519,8 +12075,11 @@ module.exports = class binance extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -10538,7 +12097,7 @@ module.exports = class binance extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -10551,10 +12110,6 @@ module.exports = class binance extends Exchange { } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } return { 'info': trade, 'timestamp': timestamp, @@ -10673,7 +12228,7 @@ module.exports = class binance extends Exchange { parseOrder (order, market = undefined) { // - // spot + // spot // // { // "symbol": "LTCBTC", @@ -10694,7 +12249,7 @@ module.exports = class binance extends Exchange { // "isWorking": true // } // - // futures + // futures // // { // "symbol": "BTCUSDT", @@ -10712,6 +12267,33 @@ module.exports = class binance extends Exchange { // "updateTime": 1499827319559 // } // + // createOrder with { "newOrderRespType": "FULL" } + // + // { + // "symbol": "BTCUSDT", + // "orderId": 5403233939, + // "orderListId": -1, + // "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e", + // "transactTime": 1617151923742, + // "price": "0.00000000", + // "origQty": "0.00050000", + // "executedQty": "0.00050000", + // "cummulativeQuoteQty": "29.47081500", + // "status": "FILLED", + // "timeInForce": "GTC", + // "type": "MARKET", + // "side": "BUY", + // "fills": [ + // { + // "price": "58941.63000000", + // "qty": "0.00050000", + // "commission": "0.00007050", + // "commissionAsset": "BNB", + // "tradeId": 737466631 + // } + // ] + // } + // const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -10721,80 +12303,26 @@ module.exports = class binance extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); // - Spot/Margin market: cummulativeQuoteQty // - Futures market: cumQuote. // Note this is not the actual cost, since Binance futures uses leverage to calculate margins. - let cost = this.safeFloat2 (order, 'cummulativeQuoteQty', 'cumQuote'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const cost = this.safeNumber2 (order, 'cummulativeQuoteQty', 'cumQuote'); const id = this.safeString (order, 'orderId'); let type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - if (this.options['parseOrderToPrecision']) { - price = parseFloat (this.priceToPrecision (symbol, price)); - } - } - } - } - } else if (type === 'limit_maker') { + if (type === 'limit_maker') { type = 'limit'; } const side = this.safeStringLower (order, 'side'); - let fee = undefined; - let trades = undefined; - const fills = this.safeValue (order, 'fills'); - if (fills !== undefined) { - trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - if (this.options['parseOrderToPrecision']) { - average = parseFloat (this.priceToPrecision (symbol, average)); - } - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const fills = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (fills, market); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = (type === 'limit_maker') || (timeInForce === 'GTX'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -10810,13 +12338,13 @@ module.exports = class binance extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -10863,8 +12391,11 @@ module.exports = class binance extends Exchange { } else { request['newClientOrderId'] = clientOrderId; } - if (market['spot']) { + if ((orderType === 'spot') || (orderType === 'margin')) { request['newOrderRespType'] = this.safeValue (this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills + } else { + // delivery and future + request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK" } // additional required fields depending on the order type let timeInForceIsRequired = false; @@ -10894,7 +12425,7 @@ module.exports = class binance extends Exchange { if (uppercaseType === 'MARKET') { const quoteOrderQty = this.safeValue (this.options, 'quoteOrderQty', false); if (quoteOrderQty) { - const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty'); + const quoteOrderQty = this.safeNumber (params, 'quoteOrderQty'); const precision = market['precision']['price']; if (quoteOrderQty !== undefined) { request['quoteOrderQty'] = this.decimalToPrecision (quoteOrderQty, TRUNCATE, precision, this.precisionMode); @@ -10914,7 +12445,7 @@ module.exports = class binance extends Exchange { } else if ((uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT')) { stopPriceIsRequired = true; quantityIsRequired = true; - if (market['future']) { + if (market['future'] || market['delivery']) { priceIsRequired = true; } } else if ((uppercaseType === 'STOP_LOSS_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) { @@ -10937,7 +12468,7 @@ module.exports = class binance extends Exchange { stopPriceIsRequired = true; } else if (uppercaseType === 'TRAILING_STOP_MARKET') { quantityIsRequired = true; - const callbackRate = this.safeFloat (params, 'callbackRate'); + const callbackRate = this.safeNumber (params, 'callbackRate'); if (callbackRate === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a callbackRate extra param for a ' + type + ' order'); } @@ -10955,7 +12486,7 @@ module.exports = class binance extends Exchange { request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -11171,10 +12702,15 @@ module.exports = class binance extends Exchange { } } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.fetchBalance (params); - const info = this.safeValue (response, 'info', {}); + const defaultType = this.safeString (this.options, 'defaultType', 'future'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + const options = this.safeValue (this.options, 'fetchPositions', {}); + const defaultMethod = (type === 'delivery') ? 'dapiPrivateGetAccount' : 'fapiPrivateV2GetAccount'; + const method = this.safeString (options, type, defaultMethod); + const response = await this[method] (params); // // futures, delivery // @@ -11217,9 +12753,44 @@ module.exports = class binance extends Exchange { // ] // } // - const positions = this.safeValue2 (info, 'positions', 'userAssets', []); - // todo unify parsePosition/parsePositions - return positions; + // fapiPrivateGetPositionRisk, dapiPrivateGetPositionRisk + // + // [ + // { + // symbol: 'XRPUSD_210625', + // positionAmt: '0', + // entryPrice: '0.00000000', + // markPrice: '0.00000000', + // unRealizedProfit: '0.00000000', + // liquidationPrice: '0', + // leverage: '20', + // maxQty: '500000', + // marginType: 'cross', + // isolatedMargin: '0.00000000', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0', + // isolatedWallet: '0' + // }, + // { + // symbol: 'BTCUSD_210326', + // positionAmt: '1', + // entryPrice: '60665.79999885', + // markPrice: '60696.76856843', + // unRealizedProfit: '0.00000084', + // liquidationPrice: '58034.68208092', + // leverage: '20', + // maxQty: '50', + // marginType: 'isolated', + // isolatedMargin: '0.00008345', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0.00164753', + // isolatedWallet: '0.00008261' + // }, + // ] + // + return this.safeValue (response, 'positions', response); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -11357,7 +12928,7 @@ module.exports = class binance extends Exchange { // const fee = { 'currency': earnedCurrency, - 'cost': this.safeFloat (trade, 'serviceChargeAmount'), + 'cost': this.safeNumber (trade, 'serviceChargeAmount'), }; let symbol = undefined; let amount = undefined; @@ -11365,13 +12936,13 @@ module.exports = class binance extends Exchange { let side = undefined; if (tradedCurrencyIsQuote) { symbol = applicantSymbol; - amount = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); - cost = this.safeFloat (trade, 'amount'); + amount = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); + cost = this.safeNumber (trade, 'amount'); side = 'buy'; } else { symbol = tradedCurrency + '/' + earnedCurrency; - amount = this.safeFloat (trade, 'amount'); - cost = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); + amount = this.safeNumber (trade, 'amount'); + cost = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); side = 'sell'; } let price = undefined; @@ -11544,8 +13115,8 @@ module.exports = class binance extends Exchange { } } const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'transactionFee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'transactionFee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -11572,6 +13143,151 @@ module.exports = class binance extends Exchange { }; } + parseTransferStatus (status) { + const statuses = { + 'CONFIRMED': 'ok', + }; + return this.safeString (statuses, status, status); + } + + parseTransfer (transfer, currency = undefined) { + // + // transfer + // + // { + // "tranId":13526853623 + // } + // + // fetchTransfers + // + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // } + // + const id = this.safeString (transfer, 'tranId'); + const currencyId = this.safeString (transfer, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const amount = this.safeNumber (transfer, 'amount'); + const type = this.safeString (transfer, 'type'); + let fromAccount = undefined; + let toAccount = undefined; + const typesByAccount = this.safeValue (this.options, 'typesByAccount', {}); + if (type !== undefined) { + const parts = type.split ('_'); + fromAccount = this.safeValue (parts, 0); + toAccount = this.safeValue (parts, 1); + fromAccount = this.safeString (typesByAccount, fromAccount, fromAccount); + toAccount = this.safeString (typesByAccount, toAccount, toAccount); + } + const timestamp = this.safeInteger (transfer, 'timestamp'); + const status = this.parseTransferStatus (this.safeString (transfer, 'status')); + return { + 'info': transfer, + 'id': id, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'currency': code, + 'amount': amount, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': status, + }; + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount, fromAccount); + const toId = this.safeString (accountsByType, toAccount, toAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'asset': currency['id'], + 'amount': this.currencyToPrecision (code, amount), + 'type': type, + }; + const response = await this.sapiPostAssetTransfer (this.extend (request, params)); + // + // { + // "tranId":13526853623 + // } + // + const transfer = this.parseTransfer (response, currency); + return this.extend (transfer, { + 'amount': amount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + }); + } + + async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const defaultType = this.safeString2 (this.options, 'fetchTransfers', 'defaultType', 'spot'); + const fromAccount = this.safeString (params, 'fromAccount', defaultType); + const defaultTo = (fromAccount === 'future') ? 'spot' : 'future'; + const toAccount = this.safeString (params, 'toAccount', defaultTo); + let type = this.safeString (params, 'type'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + if (type === undefined) { + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount parameter must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount parameter must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'type': type, + }; + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['size'] = limit; + } + const response = await this.sapiGetAssetTransfer (this.extend (request, params)); + // + // { + // total: 3, + // rows: [ + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // }, + // ] + // } + // + const rows = this.safeValue (response, 'rows', []); + return this.parseTransfers (rows, currency, since, limit); + } + async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -11634,7 +13350,7 @@ module.exports = class binance extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (detail[id], 'withdrawFee'); + withdrawFees[code] = this.safeNumber (detail[id], 'withdrawFee'); } return { 'withdraw': withdrawFees, @@ -11681,8 +13397,8 @@ module.exports = class binance extends Exchange { return { 'info': fee, 'symbol': symbol, - 'maker': this.safeFloat (fee, 'maker'), - 'taker': this.safeFloat (fee, 'taker'), + 'maker': this.safeNumber (fee, 'maker'), + 'taker': this.safeNumber (fee, 'taker'), }; } @@ -11744,7 +13460,6 @@ module.exports = class binance extends Exchange { if (api === 'wapi') { url += '.html'; } - const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); if (path === 'historicalTrades') { if (this.apiKey) { headers = { @@ -11753,19 +13468,22 @@ module.exports = class binance extends Exchange { } else { throw new AuthenticationError (this.id + ' historicalTrades endpoint requires `apiKey` credential'); } - } else if (userDataStream) { + } + const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); + if (userDataStream) { if (this.apiKey) { // v1 special case for userDataStream - body = this.urlencode (params); headers = { 'X-MBX-APIKEY': this.apiKey, 'Content-Type': 'application/x-www-form-urlencoded', }; + if (method !== 'GET') { + body = this.urlencode (params); + } } else { throw new AuthenticationError (this.id + ' userDataStream endpoint requires `apiKey` credential'); } - } - if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { + } else if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { this.checkRequiredCredentials (); let query = undefined; const recvWindow = this.safeInteger (this.options, 'recvWindow', 5000); @@ -11797,13 +13515,8 @@ module.exports = class binance extends Exchange { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } } else { - // userDataStream endpoints are public, but POST, PUT, DELETE - // therefore they don't accept URL query arguments - // https://github.com/ccxt/ccxt/issues/5224 - if (!userDataStream) { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } + if (Object.keys (params).length) { + url += '?' + this.urlencode (params); } } return { 'url': url, 'method': method, 'body': body, 'headers': headers }; @@ -11885,7 +13598,7 @@ module.exports = class binance extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],24:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],25:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -11937,13 +13650,14 @@ module.exports = class binanceus extends binance { }; -},{"./binance.js":23}],25:[function(require,module,exports){ +},{"./binance.js":24}],26:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, InvalidNonce, AuthenticationError, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -12095,12 +13809,12 @@ module.exports = class bit2c extends Exchange { const currencyId = this.currencyId (code); const uppercase = currencyId.toUpperCase (); if (uppercase in balance) { - account['free'] = this.safeFloat (balance, 'AVAILABLE_' + uppercase); - account['total'] = this.safeFloat (balance, uppercase); + account['free'] = this.safeString (balance, 'AVAILABLE_' + uppercase); + account['total'] = this.safeString (balance, uppercase); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -12119,22 +13833,22 @@ module.exports = class bit2c extends Exchange { }; const ticker = await this.publicGetExchangesPairTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const averagePrice = this.safeFloat (ticker, 'av'); - const baseVolume = this.safeFloat (ticker, 'a'); + const averagePrice = this.safeNumber (ticker, 'av'); + const baseVolume = this.safeNumber (ticker, 'a'); let quoteVolume = undefined; if (baseVolume !== undefined && averagePrice !== undefined) { quoteVolume = baseVolume * averagePrice; } - const last = this.safeFloat (ticker, 'll'); + const last = this.safeNumber (ticker, 'll'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'h'), + 'bid': this.safeNumber (ticker, 'h'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'l'), + 'ask': this.safeNumber (ticker, 'l'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -12216,14 +13930,8 @@ module.exports = class bit2c extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -12236,7 +13944,7 @@ module.exports = class bit2c extends Exchange { } const id = this.safeString (order, 'id'); const status = this.safeString (order, 'status'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -12253,12 +13961,12 @@ module.exports = class bit2c extends Exchange { 'amount': amount, 'filled': undefined, 'remaining': undefined, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -12284,16 +13992,16 @@ module.exports = class bit2c extends Exchange { parseTrade (trade, market = undefined) { let timestamp = undefined; let id = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let orderId = undefined; let feeCost = undefined; let side = undefined; const reference = this.safeString (trade, 'reference'); if (reference !== undefined) { timestamp = this.safeTimestamp (trade, 'ticks'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'firstAmount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'firstAmount'); const reference_parts = reference.split ('|'); // reference contains 'pair|orderId|tradeId' if (market === undefined) { const marketId = this.safeString (trade, 'pair'); @@ -12311,12 +14019,12 @@ module.exports = class bit2c extends Exchange { } else if (side === 1) { side = 'sell'; } - feeCost = this.safeFloat (trade, 'feeAmount'); + feeCost = this.safeNumber (trade, 'feeAmount'); } else { timestamp = this.safeTimestamp (trade, 'date'); id = this.safeString (trade, 'tid'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'amount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'amount'); side = this.safeValue (trade, 'isBid'); if (side !== undefined) { if (side) { @@ -12330,6 +14038,9 @@ module.exports = class bit2c extends Exchange { if (market !== undefined) { symbol = market['symbol']; } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -12342,7 +14053,7 @@ module.exports = class bit2c extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': { 'cost': feeCost, 'currency': 'NIS', @@ -12398,13 +14109,14 @@ module.exports = class bit2c extends Exchange { }; -},{"./base/Exchange":6,"./base/errors":8}],26:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],27:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -12479,21 +14191,23 @@ module.exports = class bitbank extends Exchange { }, }, 'markets': { + 'BAT/JPY': { 'id': 'bat_jpy', 'symbol': 'BAT/JPY', 'base': 'BAT', 'quote': 'JPY', 'baseId': 'bat', 'quoteId': 'jpy' }, + 'BAT/BTC': { 'id': 'bat_btc', 'symbol': 'BAT/BTC', 'base': 'BAT', 'quote': 'BTC', 'baseId': 'bat', 'quoteId': 'btc' }, 'BCH/BTC': { 'id': 'bcc_btc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'baseId': 'bcc', 'quoteId': 'btc' }, 'BCH/JPY': { 'id': 'bcc_jpy', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bcc', 'quoteId': 'jpy' }, + 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, + 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, + 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, + 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, + 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, 'MONA/BTC': { 'id': 'mona_btc', 'symbol': 'MONA/BTC', 'base': 'MONA', 'quote': 'BTC', 'baseId': 'mona', 'quoteId': 'btc' }, 'MONA/JPY': { 'id': 'mona_jpy', 'symbol': 'MONA/JPY', 'base': 'MONA', 'quote': 'JPY', 'baseId': 'mona', 'quoteId': 'jpy' }, 'QTUM/BTC': { 'id': 'qtum_btc', 'symbol': 'QTUM/BTC', 'base': 'QTUM', 'quote': 'BTC', 'baseId': 'qtum', 'quoteId': 'btc' }, 'QTUM/JPY': { 'id': 'qtum_jpy', 'symbol': 'QTUM/JPY', 'base': 'QTUM', 'quote': 'JPY', 'baseId': 'qtum', 'quoteId': 'jpy' }, - 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, - 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, - 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, - 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, - 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, - 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, - 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, - 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, 'XLM/BTC': { 'id': 'xlm_btc', 'symbol': 'XLM/BTC', 'base': 'XLM', 'quote': 'BTC', 'baseId': 'xlm', 'quoteId': 'btc' }, + 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, + 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, + 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, }, 'fees': { 'trading': { @@ -12542,16 +14256,16 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -12561,7 +14275,7 @@ module.exports = class bitbank extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -12597,18 +14311,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; feeCurrency = market['quote']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'transaction_id', 'trade_id'); const takerOrMaker = this.safeString (trade, 'maker_taker'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee_amount_quote'); + const feeCost = this.safeNumber (trade, 'fee_amount_quote'); if (feeCost !== undefined) { fee = { 'currency': feeCurrency, @@ -12660,11 +14371,11 @@ module.exports = class bitbank extends Exchange { // return [ this.safeInteger (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -12715,14 +14426,13 @@ module.exports = class bitbank extends Exchange { const balance = assets[i]; const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'free_amount'), - 'used': this.safeFloat (balance, 'locked_amount'), - 'total': this.safeFloat (balance, 'onhand_amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'free_amount'); + account['used'] = this.safeString (balance, 'locked_amount'); + account['total'] = this.safeString (balance, 'onhand_amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -12747,21 +14457,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (order, 'ordered_at'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'start_amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const average = this.safeFloat (order, 'average_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'start_amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const average = this.safeNumber (order, 'average_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -12775,7 +14479,7 @@ module.exports = class bitbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, @@ -12783,7 +14487,7 @@ module.exports = class bitbank extends Exchange { 'trades': undefined, 'fee': undefined, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -13026,13 +14730,14 @@ module.exports = class bitbank extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],27:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],28:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -13307,8 +15012,8 @@ module.exports = class bitbay extends Exchange { if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) { fees = this.safeValue (this.fees, 'fiat', {}); } - const maker = this.safeFloat (fees, 'maker'); - const taker = this.safeFloat (fees, 'taker'); + const maker = this.safeNumber (fees, 'maker'); + const taker = this.safeNumber (fees, 'taker'); // todo: check that the limits have ben interpreted correctly // todo: parse the fees page result.push ({ @@ -13324,7 +15029,7 @@ module.exports = class bitbay extends Exchange { 'taker': taker, 'limits': { 'amount': { - 'min': this.safeFloat (first, 'minOffer'), + 'min': this.safeNumber (first, 'minOffer'), 'max': undefined, }, 'price': { @@ -13332,7 +15037,7 @@ module.exports = class bitbay extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (second, 'minOffer'), + 'min': this.safeNumber (second, 'minOffer'), 'max': undefined, }, }, @@ -13372,16 +15077,10 @@ module.exports = class bitbay extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (order, 'time'); - const amount = this.safeFloat (order, 'startAmount'); - const remaining = this.safeFloat (order, 'currentAmount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } + const amount = this.safeNumber (order, 'startAmount'); + const remaining = this.safeNumber (order, 'currentAmount'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'info': order, @@ -13394,16 +15093,16 @@ module.exports = class bitbay extends Exchange { 'timeInForce': undefined, 'postOnly': postOnly, 'side': this.safeStringLower (order, 'offerType'), - 'price': this.safeFloat (order, 'rate'), + 'price': this.safeNumber (order, 'rate'), 'stopPrice': undefined, 'amount': amount, 'cost': undefined, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'average': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -13456,11 +15155,11 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lockedFunds'); - account['free'] = this.safeFloat (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'lockedFunds'); + account['free'] = this.safeString (balance, 'availableFunds'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -13479,22 +15178,22 @@ module.exports = class bitbay extends Exchange { }; const ticker = await this.publicGetIdTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'volume'); - const vwap = this.safeFloat (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max'), + 'low': this.safeNumber (ticker, 'min'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -13503,7 +15202,7 @@ module.exports = class bitbay extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), + 'average': this.safeNumber (ticker, 'average'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -13804,7 +15503,7 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const change = this.safeValue (item, 'change', {}); - let amount = this.safeFloat (change, 'total'); + let amount = this.safeNumber (change, 'total'); let direction = 'in'; if (amount < 0) { direction = 'out'; @@ -13816,9 +15515,9 @@ module.exports = class bitbay extends Exchange { const referenceId = this.safeString (item, 'detailId'); const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const fundsBefore = this.safeValue (item, 'fundsBefore', {}); - const before = this.safeFloat (fundsBefore, 'total'); + const before = this.safeNumber (fundsBefore, 'total'); const fundsAfter = this.safeValue (item, 'fundsAfter', {}); - const after = this.safeFloat (fundsAfter, 'total'); + const after = this.safeNumber (fundsAfter, 'total'); return { 'info': item, 'id': id, @@ -13875,11 +15574,11 @@ module.exports = class bitbay extends Exchange { const first = this.safeValue (ohlcv, 1, {}); return [ this.safeInteger (ohlcv, 0), - this.safeFloat (first, 'o'), - this.safeFloat (first, 'h'), - this.safeFloat (first, 'l'), - this.safeFloat (first, 'c'), - this.safeFloat (first, 'v'), + this.safeNumber (first, 'o'), + this.safeNumber (first, 'h'), + this.safeNumber (first, 'l'), + this.safeNumber (first, 'c'), + this.safeNumber (first, 'v'), ]; } @@ -13962,15 +15661,12 @@ module.exports = class bitbay extends Exchange { if (wasTaker !== undefined) { takerOrMaker = wasTaker ? 'taker' : 'maker'; } - const price = this.safeFloat2 (trade, 'rate', 'r'); - const amount = this.safeFloat2 (trade, 'amount', 'a'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'commissionValue'); + const priceString = this.safeString2 (trade, 'rate', 'r'); + const amountString = this.safeString2 (trade, 'amount', 'a'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'commissionValue'); const marketId = this.safeString (trade, 'market'); market = this.safeMarket (marketId, market, '-'); const symbol = market['symbol']; @@ -14302,7 +15998,7 @@ module.exports = class bitbay extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],28:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],29:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -14338,7 +16034,7 @@ module.exports = class bitcoincom extends hitbtc { } }; -},{"./hitbtc.js":93}],29:[function(require,module,exports){ +},{"./hitbtc.js":91}],30:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -14346,6 +16042,7 @@ module.exports = class bitcoincom extends hitbtc { const Exchange = require ('./base/Exchange'); const { NotSupported, RateLimitExceeded, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, InvalidNonce, BadSymbol } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -14386,6 +16083,7 @@ module.exports = class bitfinex extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': '1m', @@ -14499,6 +16197,7 @@ module.exports = class bitfinex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'maker': 0.1 / 100, @@ -14685,6 +16384,8 @@ module.exports = class bitfinex extends Exchange { 'No summary found.': ExchangeError, // fetchTradingFees (summary) endpoint can give this vague error message 'Cannot evaluate your available balance, please try again': ExchangeNotAvailable, 'Unknown symbol': BadSymbol, + 'Cannot complete transfer. Exchange balance insufficient.': InsufficientFunds, + 'Momentary balance check. Please wait few seconds and try the transfer again.': ExchangeError, }, 'broad': { 'Invalid X-BFX-SIGNATURE': AuthenticationError, @@ -14782,6 +16483,15 @@ module.exports = class bitfinex extends Exchange { 'limit': 'exchange limit', 'market': 'exchange market', }, + 'accountsByType': { + 'spot': 'exchange', + 'margin': 'trading', + 'funding': 'deposit', + 'exchange': 'exchange', + 'trading': 'trading', + 'deposit': 'deposit', + 'derivatives': 'trading', + }, }, }); } @@ -14795,7 +16505,7 @@ module.exports = class bitfinex extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdraw[code] = this.safeFloat (fees, id); + withdraw[code] = this.safeNumber (fees, id); } return { 'info': response, @@ -14831,14 +16541,31 @@ module.exports = class bitfinex extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } async fetchMarkets (params = {}) { const ids = await this.publicGetSymbols (); + // + // [ "btcusd", "ltcusd", "ltcbtc" ] + // const details = await this.publicGetSymbolsDetails (); + // + // [ + // { + // "pair":"btcusd", + // "price_precision":5, + // "initial_margin":"10.0", + // "minimum_margin":"5.0", + // "maximum_order_size":"2000.0", + // "minimum_order_size":"0.0002", + // "expiration":"NA", + // "margin":true + // }, + // ] + // const result = []; for (let i = 0; i < details.length; i++) { const market = details[i]; @@ -14869,8 +16596,8 @@ module.exports = class bitfinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -14881,6 +16608,7 @@ module.exports = class bitfinex extends Exchange { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -14889,6 +16617,8 @@ module.exports = class bitfinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': true, + 'type': 'spot', + 'margin': margin, 'precision': precision, 'limits': limits, 'info': market, @@ -14913,40 +16643,15 @@ module.exports = class bitfinex extends Exchange { return this.decimalToPrecision (price, TRUNCATE, 8, DECIMAL_PLACES); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - const code = market[key]; - const currency = this.safeValue (this.currencies, code); - if (currency !== undefined) { - const precision = this.safeInteger (currency, 'precision'); - if (precision !== undefined) { - cost = parseFloat (this.currencyToPrecision (code, cost)); - } - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); - const types = { - 'exchange': 'exchange', - 'deposit': 'funding', - 'trading': 'margin', - }; - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } const query = this.omit (params, 'type'); const response = await this.privatePostBalances (query); // [ { type: 'deposit', @@ -14962,12 +16667,16 @@ module.exports = class bitfinex extends Exchange { // amount: '0.0005', // available: '0.0005' } ], const result = { 'info': response }; + const isDerivative = requestedType === 'derivatives'; for (let i = 0; i < response.length; i++) { const balance = response[i]; const type = this.safeString (balance, 'type'); - const parsedType = this.safeString (types, type); - if ((parsedType === balanceType) || (type === balanceType)) { - const currencyId = this.safeString (balance, 'currency'); + const currencyId = this.safeStringLower (balance, 'currency', ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { const code = this.safeCurrencyCode (currencyId); // bitfinex had BCH previously, now it's BAB, but the old // BCH symbol is kept for backward-compatibility @@ -14976,13 +16685,80 @@ module.exports = class bitfinex extends Exchange { // https://github.com/ccxt/ccxt/issues/4989 if (!(code in result)) { const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currencyId = this.currencyId (code); + const fromCurrencyId = this.convertDerivativesId (currencyId, fromAccount); + const toCurrencyId = this.convertDerivativesId (currencyId, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'walletfrom': fromId, + 'walletto': toId, + }; + const response = await this.privatePostTransfer (this.extend (request, params)); + // [ + // { + // status: 'success', + // message: '0.0001 Bitcoin transfered from Margin to Exchange' + // } + // ] + const result = this.safeValue (response, 0); + const status = this.safeString (result, 'status'); + const message = this.safeString (result, 'message'); + if (message === undefined) { + throw new ExchangeError (this.id + ' transfer failed'); + } + // [{"status":"error","message":"Momentary balance check. Please wait few seconds and try the transfer again."}] + if (status === 'error') { + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + return { + 'info': response, + 'status': status, + 'amount': requestedAmount, + 'code': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'timestamp': undefined, + 'datetime': undefined, + }; + } + + convertDerivativesId (currencyId, type) { + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if ((type !== 'derivatives' && type !== 'trading' && type !== 'margin') && isDerivativeCode) { + currencyId = currencyId.slice (0, start); + } else if (type === 'derivatives' && !isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + return currencyId; } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -15021,7 +16797,7 @@ module.exports = class bitfinex extends Exchange { } parseTicker (ticker, market = undefined) { - let timestamp = this.safeFloat (ticker, 'timestamp'); + let timestamp = this.safeNumber (ticker, 'timestamp'); if (timestamp !== undefined) { timestamp *= 1000; } @@ -15044,16 +16820,16 @@ module.exports = class bitfinex extends Exchange { } } } - const last = this.safeFloat (ticker, 'last_price'); + const last = this.safeNumber (ticker, 'last_price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -15062,8 +16838,8 @@ module.exports = class bitfinex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'mid'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'mid'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -15071,24 +16847,21 @@ module.exports = class bitfinex extends Exchange { parseTrade (trade, market) { const id = this.safeString (trade, 'tid'); - let timestamp = this.safeFloat (trade, 'timestamp'); + let timestamp = this.safeNumber (trade, 'timestamp'); if (timestamp !== undefined) { timestamp = parseInt (timestamp) * 1000; } const type = undefined; const side = this.safeStringLower (trade, 'type'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; if ('fee_amount' in trade) { - const feeCost = -this.safeFloat (trade, 'fee_amount'); + const feeCost = -this.safeNumber (trade, 'fee_amount'); const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { @@ -15203,6 +16976,30 @@ module.exports = class bitfinex extends Exchange { } parseOrder (order, market = undefined) { + // + // { + // id: 57334010955, + // cid: 1611584840966, + // cid_date: null, + // gid: null, + // symbol: 'ltcbtc', + // exchange: null, + // price: '0.0042125', + // avg_execution_price: '0.0042097', + // side: 'sell', + // type: 'exchange market', + // timestamp: '1611584841.0', + // is_live: false, + // is_cancelled: false, + // is_hidden: 0, + // oco_order: 0, + // was_forced: false, + // original_amount: '0.205176', + // remaining_amount: '0.0', + // executed_amount: '0.205176', + // src: 'web' + // } + // const side = this.safeString (order, 'side'); const open = this.safeValue (order, 'is_live'); const canceled = this.safeValue (order, 'is_cancelled'); @@ -15214,30 +17011,17 @@ module.exports = class bitfinex extends Exchange { } else { status = 'closed'; } - let symbol = undefined; - if (market === undefined) { - const marketId = this.safeStringUpper (order, 'symbol'); - if (marketId !== undefined) { - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } - } - } - if (market !== undefined) { - symbol = market['symbol']; - } - let orderType = order['type']; + const marketId = this.safeStringUpper (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market); + let orderType = this.safeString (order, 'type', ''); const exchange = orderType.indexOf ('exchange ') >= 0; if (exchange) { const parts = order['type'].split (' '); orderType = parts[1]; } - let timestamp = this.safeFloat (order, 'timestamp'); - if (timestamp !== undefined) { - timestamp = parseInt (timestamp) * 1000; - } + const timestamp = this.safeTimestamp (order, 'timestamp'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -15249,17 +17033,17 @@ module.exports = class bitfinex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': side, - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_execution_price'), - 'amount': this.safeFloat (order, 'original_amount'), - 'remaining': this.safeFloat (order, 'remaining_amount'), - 'filled': this.safeFloat (order, 'executed_amount'), + 'average': this.safeNumber (order, 'avg_execution_price'), + 'amount': this.safeNumber (order, 'original_amount'), + 'remaining': this.safeNumber (order, 'remaining_amount'), + 'filled': this.safeNumber (order, 'executed_amount'), 'status': status, 'fee': undefined, 'cost': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -15314,11 +17098,11 @@ module.exports = class bitfinex extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -15466,11 +17250,11 @@ module.exports = class bitfinex extends Exchange { // "timestamp_created": "1561716066.0" // } // - let timestamp = this.safeFloat (transaction, 'timestamp_created'); + let timestamp = this.safeNumber (transaction, 'timestamp_created'); if (timestamp !== undefined) { timestamp = parseInt (timestamp * 1000); } - let updated = this.safeFloat (transaction, 'timestamp'); + let updated = this.safeNumber (transaction, 'timestamp'); if (updated !== undefined) { updated = parseInt (updated * 1000); } @@ -15478,7 +17262,7 @@ module.exports = class bitfinex extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const type = this.safeStringLower (transaction, 'type'); // DEPOSIT or WITHDRAWAL const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -15491,7 +17275,7 @@ module.exports = class bitfinex extends Exchange { 'address': this.safeString (transaction, 'address'), // todo: this is actually the tag for XRP transfers (the address is missing) 'tag': undefined, // refix it properly for the tag from description 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -15545,7 +17329,7 @@ module.exports = class bitfinex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // @@ -15623,7 +17407,7 @@ module.exports = class bitfinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],30:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],31:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -15912,6 +17696,15 @@ module.exports = class bitfinex2 extends bitfinex { 'JPY': 'JPY', 'GBP': 'GBP', }, + // actually the correct names unlike the v1 + // we don't want to extend this with accountsByType in v1 + 'v2AccountsByType': { + 'spot': 'exchange', + 'exchange': 'exchange', + 'funding': 'funding', + 'margin': 'margin', + 'derivatives': 'margin', + }, }, 'exceptions': { 'exact': { @@ -15993,8 +17786,8 @@ module.exports = class bitfinex2 extends bitfinex { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -16005,6 +17798,7 @@ module.exports = class bitfinex2 extends bitfinex { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -16019,6 +17813,7 @@ module.exports = class bitfinex2 extends bitfinex { 'type': type, 'swap': false, 'spot': spot, + 'margin': margin, 'futures': futures, }); } @@ -16131,7 +17926,7 @@ module.exports = class bitfinex2 extends bitfinex { const ids = this.safeValue (response, 0, []); const result = {}; for (let i = 0; i < ids.length; i++) { - let id = ids[i]; + const id = ids[i]; const code = this.safeCurrencyCode (id); const label = this.safeValue (indexed['label'], id, []); const name = this.safeString (label, 1); @@ -16139,13 +17934,14 @@ module.exports = class bitfinex2 extends bitfinex { const type = this.safeString (pool, 1); const feeValues = this.safeValue (indexed['fees'], id, []); const fees = this.safeValue (feeValues, 1, []); - const fee = this.safeFloat (fees, 1); + const fee = this.safeNumber (fees, 1); + const undl = this.safeValue (indexed['undl'], id, []); const precision = 8; // default precision, todo: fix "magic constants" - id = 'f' + id; + const fid = 'f' + id; result[code] = { - 'id': id, + 'id': fid, 'code': code, - 'info': [ id, label, pool, feeValues ], + 'info': [ id, label, pool, feeValues, undl ], 'type': type, 'name': name, 'active': true, @@ -16176,40 +17972,117 @@ module.exports = class bitfinex2 extends bitfinex { async fetchBalance (params = {}) { // this api call does not return the 'used' amount - use the v1 version instead (which also returns zero balances) + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 await this.loadMarkets (); - const response = await this.privatePostAuthRWallets (params); - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } + const isDerivative = requestedType === 'derivatives'; + const query = this.omit (params, 'type'); + const response = await this.privatePostAuthRWallets (query); const result = { 'info': response }; - for (let b = 0; b < response.length; b++) { - const balance = response[b]; - const accountType = balance[0]; - let currency = balance[1]; - const total = balance[2]; - const available = balance[4]; - if (accountType === balanceType) { - if (currency[0] === 't') { - currency = currency.slice (1); - } - const code = this.safeCurrencyCode (currency); + for (let i = 0; i < response.length; i++) { + const balance = response[i]; + const type = this.safeString (balance, 0); + const currencyId = this.safeStringLower (balance, 1, ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { + const code = this.safeCurrencyCode (currencyId); const account = this.account (); - // do not fill in zeroes and missing values in the parser - // rewrite and unify the following to use the unified parseBalance - account['total'] = total; - if (!available) { - if (available === 0) { - account['free'] = 0; - account['used'] = total; - } else { - account['free'] = total; - } - } else { - account['free'] = available; - account['used'] = account['total'] - account['free']; - } + account['total'] = this.safeString (balance, 2); + account['free'] = this.safeString (balance, 4); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currency = this.currency (code); + const fromCurrencyId = this.convertDerivativesId (currency, fromAccount); + const toCurrencyId = this.convertDerivativesId (currency, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + // this request is slightly different from v1 fromAccount -> from + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'from': fromId, + 'to': toId, + }; + const response = await this.privatePostAuthWTransfer (this.extend (request, params)); + // [1616451183763,"acc_tf",null,null,[1616451183763,"exchange","margin",null,"UST","UST",null,1],null,"SUCCESS","1.0 Tether USDt transfered from Exchange to Margin"] + const timestamp = this.safeInteger (response, 0); + // ["error",10001,"Momentary balance check. Please wait few seconds and try the transfer again."] + const error = this.safeString (response, 0); + if (error === 'error') { + const message = this.safeString (response, 2, ''); + // same message as in v1 + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + const info = this.safeValue (response, 4); + const fromResponse = this.safeString (info, 1); + const toResponse = this.safeString (info, 2); + const toCode = this.safeCurrencyCode (this.safeString (info, 5)); + const success = this.safeString (response, 6); + const status = (success === 'SUCCESS') ? 'ok' : undefined; + return { + 'info': response, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'status': status, + 'amount': requestedAmount, + 'code': toCode, + 'fromAccount': fromResponse, + 'toAccount': toResponse, + }; + } + + convertDerivativesId (currency, type) { + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 + // { + // id: 'fUSTF0', + // code: 'USTF0', + // info: [ 'USTF0', [], [], [], [ 'USTF0', 'UST' ] ], + const info = this.safeValue (currency, 'info'); + const transferId = this.safeString (info, 0); + const underlying = this.safeValue (info, 4, []); + let currencyId = undefined; + if (type === 'derivatives') { + currencyId = this.safeString (underlying, 0, transferId); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if (!isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + } else if (type !== 'margin') { + currencyId = this.safeString (underlying, 1, transferId); + } else { + currencyId = transferId; + } + return currencyId; } async fetchOrder (id, symbol = undefined, params = {}) { @@ -16239,9 +18112,10 @@ module.exports = class bitfinex2 extends bitfinex { const priceIndex = (fullRequest['precision'] === 'R0') ? 1 : 0; for (let i = 0; i < orderbook.length; i++) { const order = orderbook[i]; - const price = order[priceIndex]; - const amount = Math.abs (order[2]); - const side = (order[2] > 0) ? 'bids' : 'asks'; + const price = this.safeNumber (order, priceIndex); + const signedAmount = this.safeNumber (order, 2); + const amount = Math.abs (signedAmount); + const side = (signedAmount > 0) ? 'bids' : 'asks'; result[side].push ([ price, amount ]); } result['bids'] = this.sortBy (result['bids'], 0, true); @@ -16256,26 +18130,26 @@ module.exports = class bitfinex2 extends bitfinex { symbol = market['symbol']; } const length = ticker.length; - const last = ticker[length - 4]; + const last = this.safeNumber (ticker, length - 4); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': ticker[length - 2], - 'low': ticker[length - 1], - 'bid': ticker[length - 10], + 'high': this.safeNumber (ticker, length - 2), + 'low': this.safeNumber (ticker, length - 1), + 'bid': this.safeNumber (ticker, length - 10), 'bidVolume': undefined, - 'ask': ticker[length - 8], + 'ask': this.safeNumber (ticker, length - 8), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': ticker[length - 6], - 'percentage': ticker[length - 5] * 100, + 'change': this.safeNumber (ticker, length - 6), + 'percentage': this.safeNumber (ticker, length - 5) * 100, 'average': undefined, - 'baseVolume': ticker[length - 3], + 'baseVolume': this.safeNumber (ticker, length - 3), 'quoteVolume': undefined, 'info': ticker, }; @@ -16364,12 +18238,12 @@ module.exports = class bitfinex2 extends bitfinex { // const tradeLength = trade.length; const isPrivate = (tradeLength > 5); - const id = trade[0].toString (); + const id = this.safeString (trade, 0); const amountIndex = isPrivate ? 4 : 2; - let amount = trade[amountIndex]; + let amount = this.safeNumber (trade, amountIndex); let cost = undefined; const priceIndex = isPrivate ? 5 : 3; - const price = trade[priceIndex]; + const price = this.safeNumber (trade, priceIndex); let side = undefined; let orderId = undefined; let takerOrMaker = undefined; @@ -16377,7 +18251,7 @@ module.exports = class bitfinex2 extends bitfinex { let fee = undefined; let symbol = undefined; const timestampIndex = isPrivate ? 2 : 1; - const timestamp = trade[timestampIndex]; + const timestamp = this.safeInteger (trade, timestampIndex); if (isPrivate) { const marketId = trade[1]; if (marketId in this.markets_by_id) { @@ -16386,10 +18260,12 @@ module.exports = class bitfinex2 extends bitfinex { } else { symbol = this.parseSymbol (marketId); } - orderId = trade[3].toString (); - takerOrMaker = (trade[8] === 1) ? 'maker' : 'taker'; - let feeCost = trade[9]; - const feeCurrency = this.safeCurrencyCode (trade[10]); + orderId = this.safeString (trade, 3); + const maker = this.safeInteger (trade, 8); + takerOrMaker = (maker === 1) ? 'maker' : 'taker'; + let feeCost = this.safeNumber (trade, 9); + const feeCurrencyId = this.safeString (trade, 10); + const feeCurrency = this.safeCurrencyCode (feeCurrencyId); if (feeCost !== undefined) { feeCost = -feeCost; if (symbol in this.markets) { @@ -16530,10 +18406,10 @@ module.exports = class bitfinex2 extends bitfinex { // https://github.com/ccxt/ccxt/issues/6686 // const timestamp = this.safeTimestamp (order, 5); const timestamp = this.safeInteger (order, 5); - const remaining = Math.abs (this.safeFloat (order, 6)); - const amount = Math.abs (this.safeFloat (order, 7)); - const filled = amount - remaining; - const side = (order[7] < 0) ? 'sell' : 'buy'; + const remaining = Math.abs (this.safeNumber (order, 6)); + const signedAmount = this.safeNumber (order, 7); + const amount = Math.abs (signedAmount); + const side = (signedAmount < 0) ? 'sell' : 'buy'; const orderType = this.safeString (order, 8); const type = this.safeString (this.safeValue (this.options, 'exchangeTypes'), orderType); let status = undefined; @@ -16542,11 +18418,10 @@ module.exports = class bitfinex2 extends bitfinex { const parts = statusString.split (' @ '); status = this.parseOrderStatus (this.safeString (parts, 0)); } - const price = this.safeFloat (order, 16); - const average = this.safeFloat (order, 17); - const cost = price * filled; + const price = this.safeNumber (order, 16); + const average = this.safeNumber (order, 17); const clientOrderId = this.safeString (order, 2); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -16561,14 +18436,14 @@ module.exports = class bitfinex2 extends bitfinex { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -16585,11 +18460,11 @@ module.exports = class bitfinex2 extends bitfinex { if ((orderType === 'LIMIT') || (orderType === 'EXCHANGE LIMIT')) { request['price'] = this.numberToString (price); } else if ((orderType === 'STOP') || (orderType === 'EXCHANGE STOP')) { - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'STOP LIMIT') || (orderType === 'EXCHANGE STOP LIMIT')) { - const priceAuxLimit = this.safeFloat (params, 'price_aux_limit'); - let stopPrice = this.safeFloat (params, 'stopPrice'); + const priceAuxLimit = this.safeNumber (params, 'price_aux_limit'); + let stopPrice = this.safeNumber (params, 'stopPrice'); if (priceAuxLimit === undefined) { if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter or a price_aux_limit parameter for a ' + orderType + ' order'); @@ -16604,9 +18479,9 @@ module.exports = class bitfinex2 extends bitfinex { } request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'TRAILING STOP') || (orderType === 'EXCHANGE TRAILING STOP')) { - const priceTrailing = this.safeFloat (params, 'price_trailing'); + const priceTrailing = this.safeNumber (params, 'price_trailing'); request['price_trailing'] = this.numberToString (priceTrailing); - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'FOK') || (orderType === 'EXCHANGE FOK') || (orderType === 'IOC') || (orderType === 'EXCHANGE IOC')) { request['price'] = this.numberToString (price); @@ -16938,11 +18813,11 @@ module.exports = class bitfinex2 extends bitfinex { if (currency !== undefined) { code = currency['code']; } - feeCost = this.safeFloat (data, 8); + feeCost = this.safeNumber (data, 8); if (feeCost !== undefined) { feeCost = -feeCost; } - amount = this.safeFloat (data, 5); + amount = this.safeNumber (data, 5); id = this.safeValue (data, 0); status = 'ok'; if (id === 0) { @@ -16956,7 +18831,7 @@ module.exports = class bitfinex2 extends bitfinex { timestamp = this.safeInteger (transaction, 5); updated = this.safeInteger (transaction, 6); status = this.parseTransactionStatus (this.safeString (transaction, 9)); - amount = this.safeFloat (transaction, 12); + amount = this.safeNumber (transaction, 12); if (amount !== undefined) { if (amount < 0) { type = 'withdrawal'; @@ -16964,7 +18839,7 @@ module.exports = class bitfinex2 extends bitfinex { type = 'deposit'; } } - feeCost = this.safeFloat (transaction, 13); + feeCost = this.safeNumber (transaction, 13); if (feeCost !== undefined) { feeCost = -feeCost; } @@ -17092,7 +18967,7 @@ module.exports = class bitfinex2 extends bitfinex { }); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // @@ -17197,13 +19072,14 @@ module.exports = class bitfinex2 extends bitfinex { } }; -},{"./base/errors":8,"./bitfinex.js":29}],31:[function(require,module,exports){ +},{"./base/errors":9,"./bitfinex.js":30}],32:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -17385,11 +19261,11 @@ module.exports = class bitflyer extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'amount'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -17408,16 +19284,16 @@ module.exports = class bitflyer extends Exchange { }; const ticker = await this.publicGetGetticker (this.extend (request, params)); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'ltp'); + const last = this.safeNumber (ticker, 'ltp'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'best_bid'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -17427,7 +19303,7 @@ module.exports = class bitflyer extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_by_product'), + 'baseVolume': this.safeNumber (ticker, 'volume_by_product'), 'quoteVolume': undefined, 'info': ticker, }; @@ -17451,14 +19327,11 @@ module.exports = class bitflyer extends Exchange { order = this.safeString (trade, 'child_order_acceptance_id'); } const timestamp = this.parse8601 (this.safeString (trade, 'exec_date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -17534,18 +19407,17 @@ module.exports = class bitflyer extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'child_order_date')); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'outstanding_size'); - const filled = this.safeFloat (order, 'executed_size'); - const price = this.safeFloat (order, 'price'); - const cost = price * filled; + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'outstanding_size'); + const filled = this.safeNumber (order, 'executed_size'); + const price = this.safeNumber (order, 'price'); const status = this.parseOrderStatus (this.safeString (order, 'child_order_state')); const type = this.safeStringLower (order, 'child_order_type'); const side = this.safeStringLower (order, 'side'); const marketId = this.safeString (order, 'product_code'); const symbol = this.safeSymbol (marketId, market); let fee = undefined; - const feeCost = this.safeFloat (order, 'total_commission'); + const feeCost = this.safeNumber (order, 'total_commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -17554,7 +19426,7 @@ module.exports = class bitflyer extends Exchange { }; } const id = this.safeString (order, 'child_order_acceptance_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -17569,14 +19441,14 @@ module.exports = class bitflyer extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) { @@ -17639,7 +19511,7 @@ module.exports = class bitflyer extends Exchange { return this.parseTrades (response, market, since, limit); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { if (symbols === undefined) { throw new ArgumentsRequired (this.id + ' fetchPositions() requires a `symbols` argument, exactly one symbol in an array'); } @@ -17723,13 +19595,14 @@ module.exports = class bitflyer extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],32:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],33:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, OrderNotFound, InsufficientFunds, DDoSProtection, PermissionDenied, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -17985,7 +19858,7 @@ module.exports = class bitforex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -18021,14 +19894,11 @@ module.exports = class bitforex extends Exchange { const timestamp = this.safeInteger (trade, 'time'); const id = this.safeString (trade, 'tid'); const orderId = undefined; - const amount = this.safeFloat (trade, 'amount'); - const price = this.safeFloat (trade, 'price'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const sideId = this.safeInteger (trade, 'direction'); const side = this.parseSide (sideId); return { @@ -18071,12 +19941,12 @@ module.exports = class bitforex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'active'); - account['total'] = this.safeFloat (balance, 'fix'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'active'); + account['total'] = this.safeString (balance, 'fix'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTicker (symbol, params = {}) { @@ -18092,21 +19962,21 @@ module.exports = class bitforex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (data, 'high'), - 'low': this.safeFloat (data, 'low'), - 'bid': this.safeFloat (data, 'buy'), + 'high': this.safeNumber (data, 'high'), + 'low': this.safeNumber (data, 'low'), + 'bid': this.safeNumber (data, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (data, 'sell'), + 'ask': this.safeNumber (data, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (data, 'last'), - 'last': this.safeFloat (data, 'last'), + 'close': this.safeNumber (data, 'last'), + 'last': this.safeNumber (data, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (data, 'vol'), + 'baseVolume': this.safeNumber (data, 'vol'), 'quoteVolume': undefined, 'info': response, }; @@ -18126,11 +19996,11 @@ module.exports = class bitforex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -18198,26 +20068,24 @@ module.exports = class bitforex extends Exchange { parseOrder (order, market = undefined) { const id = this.safeString (order, 'orderId'); - const timestamp = this.safeFloat (order, 'createTime'); - const lastTradeTimestamp = this.safeFloat (order, 'lastTime'); + const timestamp = this.safeNumber (order, 'createTime'); + const lastTradeTimestamp = this.safeNumber (order, 'lastTime'); const symbol = market['symbol']; const sideId = this.safeInteger (order, 'tradeType'); const side = this.parseSide (sideId); const type = undefined; - const price = this.safeFloat (order, 'orderPrice'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderAmount'); - const filled = this.safeFloat (order, 'dealAmount'); - const remaining = amount - filled; + const price = this.safeNumber (order, 'orderPrice'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderAmount'); + const filled = this.safeNumber (order, 'dealAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderState')); - const cost = filled * price; const feeSide = (side === 'buy') ? 'base' : 'quote'; const feeCurrency = market[feeSide]; const fee = { - 'cost': this.safeFloat (order, 'tradeFee'), + 'cost': this.safeNumber (order, 'tradeFee'), 'currency': feeCurrency, }; - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -18231,16 +20099,15 @@ module.exports = class bitforex extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -18356,7 +20223,7 @@ module.exports = class bitforex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],33:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],34:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -18364,6 +20231,7 @@ module.exports = class bitforex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -19152,7 +21020,7 @@ module.exports = class bitget extends Exchange { let swap = false; const baseId = this.safeString2 (market, 'base_currency', 'coin'); const quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { marketType = 'swap'; spot = false; @@ -19170,7 +21038,7 @@ module.exports = class bitget extends Exchange { 'amount': parseFloat ('1e-' + sizeIncrement), 'price': parseFloat ('1e-' + tickSize), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const status = this.safeString (market, 'status'); let active = undefined; if (status !== undefined) { @@ -19427,26 +21295,26 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat2 (ticker, 'last', 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'last', 'close'); + const open = this.safeNumber (ticker, 'open'); let bidVolume = undefined; let askVolume = undefined; let bid = this.safeValue (ticker, 'bid'); if (bid === undefined) { - bid = this.safeFloat (ticker, 'best_bid'); + bid = this.safeNumber (ticker, 'best_bid'); } else { - bidVolume = this.safeFloat (bid, 1); - bid = this.safeFloat (bid, 0); + bidVolume = this.safeNumber (bid, 1); + bid = this.safeNumber (bid, 0); } let ask = this.safeValue (ticker, 'ask'); if (ask === undefined) { - ask = this.safeFloat (ticker, 'best_ask'); + ask = this.safeNumber (ticker, 'best_ask'); } else { - askVolume = this.safeFloat (ask, 1); - ask = this.safeFloat (ask, 0); + askVolume = this.safeNumber (ask, 1); + ask = this.safeNumber (ask, 0); } - const baseVolume = this.safeFloat2 (ticker, 'amount', 'volume_24h'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber2 (ticker, 'amount', 'volume_24h'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; @@ -19460,8 +21328,8 @@ module.exports = class bitget extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -19696,9 +21564,12 @@ module.exports = class bitget extends Exchange { } let timestamp = this.safeInteger (trade, 'created_at'); timestamp = this.safeInteger2 (trade, 'timestamp', 'ts', timestamp); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'filled_amount', 'order_qty'); - amount = this.safeFloat2 (trade, 'size', 'amount', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'filled_amount', 'order_qty'); + amountString = this.safeString2 (trade, 'size', 'amount', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -19717,18 +21588,13 @@ module.exports = class bitget extends Exchange { type = this.parseOrderType (side); side = this.parseOrderSide (side); } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - let feeCost = this.safeFloat (trade, 'fee'); - if (feeCost === undefined) { - feeCost = this.safeFloat (trade, 'filled_fees'); + let feeCostString = this.safeString (trade, 'fee'); + if (feeCostString === undefined) { + feeCostString = this.safeString (trade, 'filled_fees'); } else { - feeCost = -feeCost; + feeCostString = (feeCostString[0] === '-') ? feeCostString.slice (1) : feeCostString; } + const feeCost = this.parseNumber (feeCostString); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -19851,23 +21717,23 @@ module.exports = class bitget extends Exchange { const volumeIndex = this.safeString (volume, market['type'], 'amount'); return [ this.safeInteger (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets ]; } else { const volumeIndex = this.safeValue (volume, market['type'], 6); return [ this.safeInteger (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, volumeIndex), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, volumeIndex), // Base Volume ]; } } @@ -19969,13 +21835,13 @@ module.exports = class bitget extends Exchange { } const type = this.safeValue (balance, 'type'); if (type === 'trade') { - result[code]['free'] = this.safeFloat (balance, 'balance'); + result[code]['free'] = this.safeString (balance, 'balance'); } else if ((type === 'frozen') || (type === 'lock')) { - const used = this.safeFloat (result[code], 'used'); - result[code]['used'] = this.sum (used, this.safeFloat (balance, 'balance')); + const used = this.safeString (result[code], 'used'); + result[code]['used'] = Precise.stringAdd (used, this.safeString (balance, 'balance')); } } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseSwapBalance (response) { @@ -19999,11 +21865,11 @@ module.exports = class bitget extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeString (balance, 'equity'); + account['free'] = this.safeString (balance, 'total_avail_balance'); result[symbol] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchAccounts (params = {}) { @@ -20280,26 +22146,13 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let amount = this.safeFloat2 (order, 'amount', 'size'); - const filled = this.safeFloat2 (order, 'filled_amount', 'filled_qty'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - amount = Math.max (amount, filled); - remaining = Math.max (0, amount - filled); - } - } - if (type === 'market') { - remaining = 0; - } - const cost = this.safeFloat (order, 'filled_cash_amount'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); - if ((average === undefined) && (filled !== undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } + const amount = this.safeNumber2 (order, 'amount', 'size'); + const filled = this.safeNumber2 (order, 'filled_amount', 'filled_qty'); + const cost = this.safeNumber (order, 'filled_cash_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'price_avg'); const status = this.parseOrderStatus (this.safeString2 (order, 'state', 'status')); - const feeCost = this.safeFloat2 (order, 'filled_fees', 'fee'); + const feeCost = this.safeNumber2 (order, 'filled_fees', 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -20309,7 +22162,7 @@ module.exports = class bitget extends Exchange { }; } const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -20327,11 +22180,11 @@ module.exports = class bitget extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -20378,7 +22231,7 @@ module.exports = class bitget extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'amount'); + let cost = this.safeNumber (params, 'amount'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -20928,12 +22781,12 @@ module.exports = class bitget extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const txid = this.safeString (transaction, 'tx_hash'); const timestamp = this.safeInteger (transaction, 'created_at'); const updated = this.safeInteger (transaction, 'updated_at'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -21123,7 +22976,7 @@ module.exports = class bitget extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.swapGetPositionAllPosition (params); // @@ -21264,7 +23117,7 @@ module.exports = class bitget extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],34:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],35:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -21272,6 +23125,7 @@ module.exports = class bitget extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); const { DECIMAL_PLACES, SIGNIFICANT_DIGITS, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -21465,12 +23319,12 @@ module.exports = class bithumb extends Exchange { const account = this.account (); const currency = this.currency (code); const lowerCurrencyId = this.safeStringLower (currency, 'id'); - account['total'] = this.safeFloat (balances, 'total_' + lowerCurrencyId); - account['used'] = this.safeFloat (balances, 'in_use_' + lowerCurrencyId); - account['free'] = this.safeFloat (balances, 'available_' + lowerCurrencyId); + account['total'] = this.safeString (balances, 'total_' + lowerCurrencyId); + account['used'] = this.safeString (balances, 'in_use_' + lowerCurrencyId); + account['free'] = this.safeString (balances, 'available_' + lowerCurrencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -21532,8 +23386,8 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'opening_price'); - const close = this.safeFloat (ticker, 'closing_price'); + const open = this.safeNumber (ticker, 'opening_price'); + const close = this.safeNumber (ticker, 'closing_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -21544,18 +23398,18 @@ module.exports = class bithumb extends Exchange { } average = this.sum (open, close) / 2; } - const baseVolume = this.safeFloat (ticker, 'units_traded_24H'); - const quoteVolume = this.safeFloat (ticker, 'acc_trade_value_24H'); + const baseVolume = this.safeNumber (ticker, 'units_traded_24H'); + const quoteVolume = this.safeNumber (ticker, 'acc_trade_value_24H'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -21661,11 +23515,11 @@ module.exports = class bithumb extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -21755,18 +23609,16 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'units_traded', 'units'); - let cost = this.safeFloat (trade, 'total'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'units_traded', 'units'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId); @@ -21969,14 +23821,14 @@ module.exports = class bithumb extends Exchange { const sideProperty = this.safeValue2 (order, 'type', 'side'); const side = (sideProperty === 'bid') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'order_status')); - let price = this.safeFloat2 (order, 'order_price', 'price'); + let price = this.safeNumber2 (order, 'order_price', 'price'); let type = 'limit'; if (price === 0) { price = undefined; type = 'market'; } - const amount = this.safeFloat2 (order, 'order_qty', 'units'); - let remaining = this.safeFloat (order, 'units_remaining'); + const amount = this.safeNumber2 (order, 'order_qty', 'units'); + let remaining = this.safeNumber (order, 'units_remaining'); if (remaining === undefined) { if (status === 'closed') { remaining = 0; @@ -21995,65 +23847,14 @@ module.exports = class bithumb extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let filled = undefined; - let cost = undefined; - let average = undefined; const id = this.safeString (order, 'order_id'); - const rawTrades = this.safeValue (order, 'contract'); - let trades = undefined; - let fee = undefined; - let fees = undefined; - let feesByCurrency = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'side': side, - 'symbol': symbol, - 'order': id, - }); - filled = 0; - feesByCurrency = {}; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - filled = this.sum (filled, trade['amount']); - cost = this.sum (cost, trade['cost']); - const tradeFee = trade['fee']; - const feeCurrency = tradeFee['currency']; - if (feeCurrency in feesByCurrency) { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': this.sum (feesByCurrency[feeCurrency]['cost'], tradeFee['cost']), - }; - } else { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': tradeFee['cost'], - }; - } - } - const feeCurrencies = Object.keys (feesByCurrency); - const feeCurrenciesLength = feeCurrencies.length; - if (feeCurrenciesLength > 1) { - fees = []; - for (let i = 0; i < feeCurrencies.length; i++) { - const feeCurrency = feeCurrencies[i]; - fees.push (feesByCurrency[feeCurrency]); - } - } else { - fee = this.safeValue (feesByCurrency, feeCurrencies[0]); - } - if (filled !== 0) { - average = cost / filled; - } - } - if (amount !== undefined) { - if ((filled === undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if ((remaining === undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const result = { + const rawTrades = this.safeValue (order, 'contract', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'side': side, + 'symbol': symbol, + 'order': id, + }); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -22068,20 +23869,14 @@ module.exports = class bithumb extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, + 'cost': undefined, + 'average': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': trades, - }; - if (fee !== undefined) { - result['fee'] = fee; - } else if (fees !== undefined) { - result['fees'] = fees; - } - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -22241,7 +24036,7 @@ module.exports = class bithumb extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],35:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],36:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -22272,7 +24067,7 @@ module.exports = class bitkk extends zb { } }; -},{"./zb.js":182}],36:[function(require,module,exports){ +},{"./zb.js":178}],37:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -22710,16 +24505,16 @@ module.exports = class bitmart extends Exchange { // const pricePrecision = this.safeInteger (market, 'price_max_precision'); const precision = { - 'amount': this.safeFloat (market, 'base_min_size'), + 'amount': this.safeNumber (market, 'base_min_size'), 'price': parseFloat (this.decimalToPrecision (Math.pow (10, -pricePrecision), ROUND, 10)), }; - const minBuyCost = this.safeFloat (market, 'min_buy_amount'); - const minSellCost = this.safeFloat (market, 'min_sell_amount'); + const minBuyCost = this.safeNumber (market, 'min_buy_amount'); + const minSellCost = this.safeNumber (market, 'min_sell_amount'); const minCost = Math.max (minBuyCost, minSellCost); const limits = { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': { 'min': undefined, @@ -22829,16 +24624,16 @@ module.exports = class bitmart extends Exchange { // // the docs are wrong: https://github.com/ccxt/ccxt/issues/5612 // - const amountPrecision = this.safeFloat (contract, 'vol_unit'); - const pricePrecision = this.safeFloat (contract, 'price_unit'); + const amountPrecision = this.safeNumber (contract, 'vol_unit'); + const pricePrecision = this.safeNumber (contract, 'price_unit'); const precision = { 'amount': amountPrecision, 'price': pricePrecision, }; const limits = { 'amount': { - 'min': this.safeFloat (contract, 'min_vol'), - 'max': this.safeFloat (contract, 'max_vol'), + 'min': this.safeNumber (contract, 'min_vol'), + 'max': this.safeNumber (contract, 'max_vol'), }, 'price': { 'min': undefined, @@ -22861,8 +24656,8 @@ module.exports = class bitmart extends Exchange { future = true; } const feeConfig = this.safeValue (market, 'fee_config', {}); - const maker = this.safeFloat (feeConfig, 'maker_fee'); - const taker = this.safeFloat (feeConfig, 'taker_fee'); + const maker = this.safeNumber (feeConfig, 'maker_fee'); + const taker = this.safeNumber (feeConfig, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -22950,33 +24745,33 @@ module.exports = class bitmart extends Exchange { const timestamp = this.safeTimestamp (ticker, 'timestamp', this.milliseconds ()); const marketId = this.safeString2 (ticker, 'symbol', 'contract_id'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat2 (ticker, 'close_24h', 'last_price'); - let percentage = this.safeFloat (ticker, 'fluctuation', 'rise_fall_rate'); + const last = this.safeNumber2 (ticker, 'close_24h', 'last_price'); + let percentage = this.safeNumber (ticker, 'fluctuation', 'rise_fall_rate'); if (percentage !== undefined) { percentage *= 100; } - const baseVolume = this.safeFloat2 (ticker, 'base_volume_24h', 'base_coin_volume'); - const quoteVolume = this.safeFloat2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); + const baseVolume = this.safeNumber2 (ticker, 'base_volume_24h', 'base_coin_volume'); + const quoteVolume = this.safeNumber2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const open = this.safeFloat2 (ticker, 'open_24h', 'open'); + const open = this.safeNumber2 (ticker, 'open_24h', 'open'); let average = undefined; if ((last !== undefined) && (open !== undefined)) { average = this.sum (last, open) / 2; } - average = this.safeFloat (ticker, 'avg_price', average); + average = this.safeNumber (ticker, 'avg_price', average); const price = this.safeValue (ticker, 'depth_price', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), - 'bid': this.safeFloat (price, 'best_bid', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (price, 'best_ask', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), + 'bid': this.safeNumber (price, 'best_bid', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (price, 'best_ask', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open_24h'), + 'open': this.safeNumber (ticker, 'open_24h'), 'close': last, 'last': last, 'previousClose': undefined, @@ -23280,18 +25075,18 @@ module.exports = class bitmart extends Exchange { if (execType !== undefined) { takerOrMaker = (execType === 'M') ? 'maker' : 'taker'; } - let price = this.safeFloat2 (trade, 'price', 'deal_price'); - price = this.safeFloat (trade, 'price_avg', price); - let amount = this.safeFloat2 (trade, 'amount', 'deal_vol'); - amount = this.safeFloat (trade, 'size', amount); - let cost = this.safeFloat2 (trade, 'count', 'notional'); + let price = this.safeNumber2 (trade, 'price', 'deal_price'); + price = this.safeNumber (trade, 'price_avg', price); + let amount = this.safeNumber2 (trade, 'amount', 'deal_vol'); + amount = this.safeNumber (trade, 'size', amount); + let cost = this.safeNumber2 (trade, 'count', 'notional'); if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { cost = amount * price; } const orderId = this.safeInteger (trade, 'order_id'); const marketId = this.safeString2 (trade, 'contract_id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (trade, 'fees'); + const feeCost = this.safeNumber (trade, 'fees'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_coin_name'); @@ -23419,11 +25214,11 @@ module.exports = class bitmart extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -23750,11 +25545,11 @@ module.exports = class bitmart extends Exchange { currencyId = this.safeString (balance, 'coind_code', currencyId); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat2 (balance, 'available', 'available_vol'); - account['used'] = this.safeFloat2 (balance, 'frozen', 'freeze_vol'); + account['free'] = this.safeString2 (balance, 'available', 'available_vol'); + account['used'] = this.safeString2 (balance, 'frozen', 'freeze_vol'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -23823,29 +25618,10 @@ module.exports = class bitmart extends Exchange { if (market !== undefined) { status = this.parseOrderStatusByType (market['type'], this.safeString (order, 'status')); } - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat2 (order, 'price_avg', 'done_avg_price'); - const amount = this.safeFloat2 (order, 'size', 'vol'); - let cost = undefined; - let filled = this.safeFloat2 (order, 'filled_size', 'done_vol'); - let remaining = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - if (filled === undefined) { - filled = Math.max (0, amount - remaining); - } - } - if (filled !== undefined) { - if (remaining === undefined) { - remaining = Math.max (0, amount - filled); - } - if (cost === undefined) { - if (average !== undefined) { - cost = average * filled; - } - } - } - } + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber2 (order, 'price_avg', 'done_avg_price'); + const amount = this.safeNumber2 (order, 'size', 'vol'); + const filled = this.safeNumber2 (order, 'filled_size', 'done_vol'); let side = this.safeString (order, 'side'); // 1 = Open long // 2 = Close short @@ -23867,7 +25643,7 @@ module.exports = class bitmart extends Exchange { average = undefined; } } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -23882,14 +25658,14 @@ module.exports = class bitmart extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatusByType (type, status) { @@ -23930,7 +25706,7 @@ module.exports = class bitmart extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -24516,12 +26292,12 @@ module.exports = class bitmart extends Exchange { type = 'deposit'; id = depositId; } - const amount = this.safeFloat (transaction, 'arrival_amount'); + const amount = this.safeNumber (transaction, 'arrival_amount'); const timestamp = this.safeInteger (transaction, 'tapply_timeime'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -24637,1735 +26413,7 @@ module.exports = class bitmart extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],37:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); - -// --------------------------------------------------------------------------- - -module.exports = class bitmax extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'bitmax', - 'name': 'BitMax', - 'countries': [ 'CN' ], // China - 'rateLimit': 500, - // new metainfo interface - 'has': { - 'CORS': false, - 'fetchMarkets': true, - 'fetchCurrencies': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchOHLCV': true, - 'fetchTrades': true, - 'fetchAccounts': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'cancelAllOrders': true, - 'fetchDepositAddress': true, - 'fetchTransactions': true, - 'fetchDeposits': true, - 'fetchWithdrawals': true, - 'fetchOrder': true, - 'fetchOrders': true, - 'fetchOpenOrders': true, - 'fetchClosedOrders': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '6h': '360', - '12h': '720', - '1d': '1d', - '1w': '1w', - '1M': '1m', - }, - 'version': 'v1', - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg', - 'api': 'https://bitmax.io', - 'test': 'https://bitmax-test.io', - 'www': 'https://bitmax.io', - 'doc': [ - 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', - ], - 'fees': 'https://bitmax.io/#/feeRate/tradeRate', - 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', - }, - 'api': { - 'public': { - 'get': [ - 'assets', - 'products', - 'ticker', - 'barhist/info', - 'barhist', - 'depth', - 'trades', - 'cash/assets', // not documented - 'cash/products', // not documented - 'margin/assets', // not documented - 'margin/products', // not documented - 'futures/collateral', - 'futures/contracts', - 'futures/ref-px', - 'futures/market-data', - 'futures/funding-rates', - ], - }, - 'accountCategory': { - 'get': [ - 'balance', - 'order/open', - 'order/status', - 'order/hist/current', - 'risk', - ], - 'post': [ - 'order', - 'order/batch', - ], - 'delete': [ - 'order', - 'order/all', - 'order/batch', - ], - }, - 'accountGroup': { - 'get': [ - 'cash/balance', - 'margin/balance', - 'margin/risk', - 'transfer', - 'futures/collateral-balance', - 'futures/position', - 'futures/risk', - 'futures/funding-payments', - 'order/hist', - ], - 'post': [ - 'futures/transfer/deposit', - 'futures/transfer/withdraw', - ], - }, - 'private': { - 'get': [ - 'info', - 'wallet/transactions', - 'wallet/deposit/address', // not documented - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'taker': 0.002, - 'maker': 0.002, - }, - }, - 'precisionMode': TICK_SIZE, - 'options': { - 'account-category': 'cash', // 'cash'/'margin'/'futures' - 'account-group': undefined, - 'fetchClosedOrders': { - 'method': 'accountGroupGetOrderHist', // 'accountGroupGetAccountCategoryOrderHistCurrent' - }, - }, - 'exceptions': { - 'exact': { - // not documented - '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"} - '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"} - '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"} - '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."} - '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'} - '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' } - '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."} - // documented - '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid - '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing - '100003': BadRequest, // KEY_CONFLICT The same key exists already - '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument - '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument - '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid - '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption - '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request - '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request - '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account - '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp - '100012': BadRequest, // INVALID_STR_FORMAT String format does not - '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input - '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error - '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object - '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed - '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times - '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist - '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly - '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist - '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error - '200007': ExchangeError, // CODE_NOT_FOUND - '200008': ExchangeError, // CODE_EXPIRED Code expired - '200009': ExchangeError, // CODE_MISMATCH Code does not match - '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword - '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly - '200012': ExchangeError, // FAKE_COKE_VERIFY - '200013': ExchangeError, // SECURITY_ALERT Provide security alert message - '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw. - '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation - '300001': InvalidOrder, // INVALID_PRICE Order price is invalid - '300002': InvalidOrder, // INVALID_QTY Order size is invalid - '300003': InvalidOrder, // INVALID_SIDE Order side is invalid - '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large - '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid - '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid - '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid - '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid - '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset - '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading - '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange - '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request - '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset - '300021': InvalidOrder, // TRADING_DISABLED Trading is disabled on account or asset - '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading - '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance - '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading - '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high - '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading - '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price - '510001': ExchangeError, // SERVER_ERROR Something wrong with server. - '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass - }, - 'broad': {}, - }, - 'commonCurrencies': { - 'BTCBEAR': 'BEAR', - 'BTCBULL': 'BULL', - }, - }); - } - - getAccount (params = {}) { - // get current or provided bitmax sub-account - const account = this.safeValue (params, 'account', this.options['account']); - return account.toLowerCase ().capitalize (); - } - - async fetchCurrencies (params = {}) { - const assets = await this.publicGetAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode" : "LTCBULL", - // "assetName" : "3X Long LTC Token", - // "precisionScale" : 9, - // "nativeScale" : 4, - // "withdrawalFee" : "0.2", - // "minWithdrawalAmt" : "1.0", - // "status" : "Normal" - // }, - // ] - // } - // - const margin = await this.publicGetMarginAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode":"BTT", - // "borrowAssetCode":"BTT-B", - // "interestAssetCode":"BTT-I", - // "nativeScale":0, - // "numConfirmations":1, - // "withdrawFee":"100.0", - // "minWithdrawalAmt":"1000.0", - // "statusCode":"Normal", - // "statusMessage":"", - // "interestRate":"0.001" - // } - // ] - // } - // - const cash = await this.publicGetCashAssets (params); - // - // { - // "code":0, - // "data":[ - // { - // "assetCode":"LTCBULL", - // "nativeScale":4, - // "numConfirmations":20, - // "withdrawFee":"0.2", - // "minWithdrawalAmt":"1.0", - // "statusCode":"Normal", - // "statusMessage":"" - // } - // ] - // } - // - const assetsData = this.safeValue (assets, 'data', []); - const marginData = this.safeValue (margin, 'data', []); - const cashData = this.safeValue (cash, 'data', []); - const assetsById = this.indexBy (assetsData, 'assetCode'); - const marginById = this.indexBy (marginData, 'assetCode'); - const cashById = this.indexBy (cashData, 'assetCode'); - const dataById = this.deepExtend (assetsById, marginById, cashById); - const ids = Object.keys (dataById); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const currency = dataById[id]; - const code = this.safeCurrencyCode (id); - const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); - // why would the exchange API have different names for the same field - const fee = this.safeFloat2 (currency, 'withdrawFee', 'withdrawalFee'); - const status = this.safeString2 (currency, 'status', 'statusCode'); - const active = (status === 'Normal'); - const margin = ('borrowAssetCode' in currency); - result[code] = { - 'id': id, - 'code': code, - 'info': currency, - 'type': undefined, - 'margin': margin, - 'name': this.safeString (currency, 'assetName'), - 'active': active, - 'fee': fee, - 'precision': precision, - 'limits': { - 'amount': { - 'min': Math.pow (10, -precision), - 'max': undefined, - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': undefined, - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawalAmt'), - 'max': undefined, - }, - }, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - const products = await this.publicGetProducts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"LBA/BTC", - // "baseAsset":"LBA", - // "quoteAsset":"BTC", - // "status":"Normal", - // "minNotional":"0.000625", - // "maxNotional":"6.25", - // "marginTradable":false, - // "commissionType":"Quote", - // "commissionReserveRate":"0.001", - // "tickSize":"0.000000001", - // "lotSize":"1" - // }, - // ] - // } - // - const cash = await this.publicGetCashProducts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"QTUM/BTC", - // "domain":"BTC", - // "tradingStartTime":1569506400000, - // "collapseDecimals":"0.0001,0.000001,0.00000001", - // "minQty":"0.000000001", - // "maxQty":"1000000000", - // "minNotional":"0.000625", - // "maxNotional":"12.5", - // "statusCode":"Normal", - // "statusMessage":"", - // "tickSize":"0.00000001", - // "useTick":false, - // "lotSize":"0.1", - // "useLot":false, - // "commissionType":"Quote", - // "commissionReserveRate":"0.001", - // "qtyScale":1, - // "priceScale":8, - // "notionalScale":4 - // } - // ] - // } - // - const futures = await this.publicGetFuturesContracts (params); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"BTC-PERP", - // "tradingStartTime":1579701600000, - // "collapseDecimals":"1,0.1,0.01", - // "minQty":"0.000000001", - // "maxQty":"1000000000", - // "minNotional":"5", - // "maxNotional":"1000000", - // "statusCode":"Normal", - // "statusMessage":"", - // "tickSize":"0.25", - // "lotSize":"0.0001", - // "priceScale":2, - // "qtyScale":4, - // "notionalScale":2 - // } - // ] - // } - // - const productsData = this.safeValue (products, 'data', []); - const productsById = this.indexBy (productsData, 'symbol'); - const cashData = this.safeValue (cash, 'data', []); - const futuresData = this.safeValue (futures, 'data', []); - const cashAndFuturesData = this.arrayConcat (cashData, futuresData); - const cashAndFuturesById = this.indexBy (cashAndFuturesData, 'symbol'); - const dataById = this.deepExtend (productsById, cashAndFuturesById); - const ids = Object.keys (dataById); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const market = dataById[id]; - const baseId = this.safeString (market, 'baseAsset'); - const quoteId = this.safeString (market, 'quoteAsset'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), - }; - const status = this.safeString (market, 'status'); - const active = (status === 'Normal'); - const type = ('useLot' in market) ? 'spot' : 'future'; - const spot = (type === 'spot'); - const future = (type === 'future'); - let symbol = id; - if (!future) { - symbol = base + '/' + quote; - } - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'type': type, - 'spot': spot, - 'future': future, - 'active': active, - 'precision': precision, - 'limits': { - 'amount': { - 'min': this.safeFloat (market, 'minQty'), - 'max': this.safeFloat (market, 'maxQty'), - }, - 'price': { - 'min': this.safeFloat (market, 'tickSize'), - 'max': undefined, - }, - 'cost': { - 'min': this.safeFloat (market, 'minNotional'), - 'max': this.safeFloat (market, 'maxNotional'), - }, - }, - }); - } - return result; - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - // TODO: fee calculation here is incorrect, we need to support tiered fee calculation. - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - - async fetchAccounts (params = {}) { - let accountGroup = this.safeString (this.options, 'account-group'); - let response = undefined; - if (accountGroup === undefined) { - response = await this.privateGetInfo (params); - // - // { - // "code":0, - // "data":{ - // "email":"igor.kroitor@gmail.com", - // "accountGroup":8, - // "viewPermission":true, - // "tradePermission":true, - // "transferPermission":true, - // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"], - // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"], - // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"], - // "userUID":"U6491137460" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - accountGroup = this.safeString (data, 'accountGroup'); - this.options['account-group'] = accountGroup; - } - return [ - { - 'id': accountGroup, - 'type': undefined, - 'currency': undefined, - 'info': response, - }, - ]; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchBalance', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeString (account, 'id'); - const request = { - 'account-group': accountGroup, - }; - let method = 'accountCategoryGetBalance'; - if (accountCategory === 'futures') { - method = 'accountGroupGetFuturesCollateralBalance'; - } else { - request['account-category'] = accountCategory; - } - const response = await this[method] (this.extend (request, params)); - // - // cash - // - // { - // 'code': 0, - // 'data': [ - // { - // 'asset': 'BCHSV', - // 'totalBalance': '64.298000048', - // 'availableBalance': '64.298000048', - // }, - // ] - // } - // - // margin - // - // { - // 'code': 0, - // 'data': [ - // { - // 'asset': 'BCHSV', - // 'totalBalance': '64.298000048', - // 'availableBalance': '64.298000048', - // 'borrowed': '0', - // 'interest': '0', - // }, - // ] - // } - // - // futures - // - // { - // "code":0, - // "data":[ - // {"asset":"BTC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"9456.59"}, - // {"asset":"ETH","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"235.95"}, - // {"asset":"USDT","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"}, - // {"asset":"USDC","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00035"}, - // {"asset":"PAX","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1.00045"}, - // {"asset":"USDTR","totalBalance":"0","availableBalance":"0","maxTransferrable":"0","priceInUSDT":"1"} - // ] - // } - // - const result = { 'info': response }; - const balances = this.safeValue (response, 'data', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - const response = await this.publicGetDepth (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "m":"depth-snapshot", - // "symbol":"BTC-PERP", - // "data":{ - // "ts":1590223998202, - // "seqnum":115444921, - // "asks":[ - // ["9207.5","18.2383"], - // ["9207.75","18.8235"], - // ["9208","10.7873"], - // ], - // "bids":[ - // ["9207.25","0.4009"], - // ["9207","0.003"], - // ["9206.5","0.003"], - // ] - // } - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const orderbook = this.safeValue (data, 'data', {}); - const timestamp = this.safeInteger (orderbook, 'ts'); - const result = this.parseOrderBook (orderbook, timestamp); - result['nonce'] = this.safeInteger (orderbook, 'seqnum'); - return result; - } - - parseTicker (ticker, market = undefined) { - // - // { - // "symbol":"QTUM/BTC", - // "open":"0.00016537", - // "close":"0.00019077", - // "high":"0.000192", - // "low":"0.00016537", - // "volume":"846.6", - // "ask":["0.00018698","26.2"], - // "bid":["0.00018408","503.7"], - // "type":"spot" - // } - // - const timestamp = undefined; - const marketId = this.safeString (ticker, 'symbol'); - let symbol = undefined; - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } else if (marketId !== undefined) { - const type = this.safeString (ticker, 'type'); - if (type === 'spot') { - const [ baseId, quoteId ] = marketId.split ('/'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - } - } - if ((symbol === undefined) && (market !== undefined)) { - symbol = market['symbol']; - } - const close = this.safeFloat (ticker, 'close'); - const bid = this.safeValue (ticker, 'bid', []); - const ask = this.safeValue (ticker, 'ask', []); - const open = this.safeFloat (ticker, 'open'); - let change = undefined; - let percentage = undefined; - let average = undefined; - if ((open !== undefined) && (close !== undefined)) { - change = close - open; - if (open > 0) { - percentage = change / open * 100; - } - average = this.sum (open, close) / 2; - } - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 0), - 'bidVolume': this.safeFloat (bid, 1), - 'ask': this.safeFloat (ask, 0), - 'askVolume': this.safeFloat (ask, 1), - 'vwap': undefined, - 'open': open, - 'close': close, - 'last': close, - 'previousClose': undefined, // previous day close - 'change': change, - 'percentage': percentage, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - const response = await this.publicGetTicker (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "symbol":"BTC-PERP", // or "BTC/USDT" - // "open":"9073", - // "close":"9185.75", - // "high":"9185.75", - // "low":"9185.75", - // "volume":"576.8334", - // "ask":["9185.75","15.5863"], - // "bid":["9185.5","0.003"], - // "type":"derivatives", // or "spot" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - return this.parseTicker (data, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const request = {}; - if (symbols !== undefined) { - const marketIds = this.marketIds (symbols); - request['symbol'] = marketIds.join (','); - } - const response = await this.publicGetTicker (this.extend (request, params)); - // - // { - // "code":0, - // "data":[ - // { - // "symbol":"QTUM/BTC", - // "open":"0.00016537", - // "close":"0.00019077", - // "high":"0.000192", - // "low":"0.00016537", - // "volume":"846.6", - // "ask":["0.00018698","26.2"], - // "bid":["0.00018408","503.7"], - // "type":"spot" - // } - // ] - // } - // - const data = this.safeValue (response, 'data', []); - return this.parseTickers (data, symbols); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "m":"bar", - // "s":"BTC/USDT", - // "data":{ - // "i":"1", - // "ts":1590228000000, - // "o":"9139.59", - // "c":"9131.94", - // "h":"9139.99", - // "l":"9121.71", - // "v":"25.20648" - // } - // } - // - const data = this.safeValue (ohlcv, 'data', {}); - return [ - this.safeInteger (data, 'ts'), - this.safeFloat (data, 'o'), - this.safeFloat (data, 'h'), - this.safeFloat (data, 'l'), - this.safeFloat (data, 'c'), - this.safeFloat (data, 'v'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - 'interval': this.timeframes[timeframe], - }; - // if since and limit are not specified - // the exchange will return just 1 last candle by default - const duration = this.parseTimeframe (timeframe); - const options = this.safeValue (this.options, 'fetchOHLCV', {}); - const defaultLimit = this.safeInteger (options, 'limit', 500); - if (since !== undefined) { - request['from'] = since; - if (limit === undefined) { - limit = defaultLimit; - } else { - limit = Math.min (limit, defaultLimit); - } - request['to'] = this.sum (since, limit * duration * 1000, 1); - } else if (limit !== undefined) { - request['n'] = limit; // max 500 - } - const response = await this.publicGetBarhist (this.extend (request, params)); - // - // { - // "code":0, - // "data":[ - // { - // "m":"bar", - // "s":"BTC/USDT", - // "data":{ - // "i":"1", - // "ts":1590228000000, - // "o":"9139.59", - // "c":"9131.94", - // "h":"9139.99", - // "l":"9121.71", - // "v":"25.20648" - // } - // } - // ] - // } - // - const data = this.safeValue (response, 'data', []); - return this.parseOHLCVs (data, market, timeframe, since, limit); - } - - parseTrade (trade, market = undefined) { - // - // public fetchTrades - // - // { - // "p":"9128.5", // price - // "q":"0.0030", // quantity - // "ts":1590229002385, // timestamp - // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade - // "seqnum":180143985289898554 - // } - // - const timestamp = this.safeInteger (trade, 'ts'); - const price = this.safeFloat2 (trade, 'price', 'p'); - const amount = this.safeFloat (trade, 'q'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } - const buyerIsMaker = this.safeValue (trade, 'bm', false); - const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; - const side = buyerIsMaker ? 'buy' : 'sell'; - let symbol = undefined; - if ((symbol === undefined) && (market !== undefined)) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'id': undefined, - 'order': undefined, - 'type': undefined, - 'takerOrMaker': makerOrTaker, - 'side': side, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'symbol': market['id'], - }; - if (limit !== undefined) { - request['n'] = limit; // max 100 - } - const response = await this.publicGetTrades (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "m":"trades", - // "symbol":"BTC-PERP", - // "data":[ - // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554}, - // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587}, - // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043} - // ] - // } - // } - // - const records = this.safeValue (response, 'data', []); - const trades = this.safeValue (records, 'data', []); - return this.parseTrades (trades, market, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'PendingNew': 'open', - 'New': 'open', - 'PartiallyFilled': 'open', - 'Filled': 'closed', - 'Canceled': 'canceled', - 'Rejected': 'rejected', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - // - // createOrder - // - // { - // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", - // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", - // "orderType": "Market", - // "symbol": "BTC/USDT", - // "timestamp": 1573576916201 - // } - // - // fetchOrder, fetchOpenOrders, fetchClosedOrders - // - // { - // "symbol": "BTC/USDT", - // "price": "8131.22", - // "orderQty": "0.00082", - // "orderType": "Market", - // "avgPx": "7392.02", - // "cumFee": "0.005152238", - // "cumFilledQty": "0.00082", - // "errorCode": "", - // "feeAsset": "USDT", - // "lastExecTime": 1575953151764, - // "orderId": "a16eee20b6750866943712zWEDdAjt3", - // "seqNum": 2623469, - // "side": "Buy", - // "status": "Filled", - // "stopPrice": "", - // "execInst": "NULL_VAL" - // } - // - // { - // "ac": "FUTURES", - // "accountId": "testabcdefg", - // "avgPx": "0", - // "cumFee": "0", - // "cumQty": "0", - // "errorCode": "NULL_VAL", - // "execInst": "NULL_VAL", - // "feeAsset": "USDT", - // "lastExecTime": 1584072844085, - // "orderId": "r170d21956dd5450276356bbtcpKa74", - // "orderQty": "1.1499", - // "orderType": "Limit", - // "price": "4000", - // "sendingTime": 1584072841033, - // "seqNum": 24105338, - // "side": "Buy", - // "status": "Canceled", - // "stopPrice": "", - // "symbol": "BTC-PERP" - // }, - // - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'symbol'); - const symbol = this.safeSymbol (marketId, market, '/'); - let timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); - let lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const average = this.safeFloat (order, 'avgPx'); - const filled = this.safeFloat2 (order, 'cumFilledQty', 'cumQty'); - let remaining = undefined; - if (filled !== undefined) { - if (filled === 0) { - timestamp = lastTradeTimestamp; - lastTradeTimestamp = undefined; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - let cost = undefined; - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - const id = this.safeString (order, 'orderId'); - let clientOrderId = this.safeString (order, 'id'); - if (clientOrderId !== undefined) { - if (clientOrderId.length < 1) { - clientOrderId = undefined; - } - } - const type = this.safeStringLower (order, 'orderType'); - const side = this.safeStringLower (order, 'side'); - const feeCost = this.safeFloat (order, 'cumFee'); - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (order, 'feeAsset'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': stopPrice, - 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, - 'remaining': remaining, - 'status': status, - 'fee': fee, - 'trades': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const market = this.market (symbol); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'createOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'symbol': market['id'], - 'time': this.milliseconds (), - 'orderQty': this.amountToPrecision (symbol, amount), - 'orderType': type, // "limit", "market", "stop_market", "stop_limit" - 'side': side, // "buy" or "sell" - // 'orderPrice': this.priceToPrecision (symbol, price), - // 'stopPrice': this.priceToPrecision (symbol, stopPrice), // required for stop orders - // 'postOnly': 'false', // 'false', 'true' - // 'timeInForce': 'GTC', // GTC, IOC, FOK - // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE - }; - if (clientOrderId !== undefined) { - request['id'] = clientOrderId; - params = this.omit (params, [ 'clientOrderId', 'id' ]); - } - if ((type === 'limit') || (type === 'stop_limit')) { - request['orderPrice'] = this.priceToPrecision (symbol, price); - } - if ((type === 'stop_limit') || (type === 'stop_market')) { - const stopPrice = this.safeFloat (params, 'stopPrice'); - if (stopPrice === undefined) { - throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); - } else { - request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); - params = this.omit (params, 'stopPrice'); - } - } - const response = await this.accountCategoryPostOrder (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "ac": "MARGIN", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "action": "place-order", - // "info": { - // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa", - // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830", - // "orderType": "Market", - // "symbol": "BTC/USDT", - // "timestamp": 1573576916201 - // }, - // "status": "Ack" - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const info = this.safeValue (data, 'info', {}); - return this.parseOrder (info, market); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'orderId': id, - }; - const response = await this.accountCategoryGetOrderStatus (this.extend (request, params)); - // - // { - // "code": 0, - // "accountCategory": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "data": [ - // { - // "symbol": "BTC/USDT", - // "price": "8131.22", - // "orderQty": "0.00082", - // "orderType": "Market", - // "avgPx": "7392.02", - // "cumFee": "0.005152238", - // "cumFilledQty": "0.00082", - // "errorCode": "", - // "feeAsset": "USDT", - // "lastExecTime": 1575953151764, - // "orderId": "a16eee20b6750866943712zWEDdAjt3", - // "seqNum": 2623469, - // "side": "Buy", - // "status": "Filled", - // "stopPrice": "", - // "execInst": "NULL_VAL" - // } - // ] - // } - // - const data = this.safeValue (response, 'data', {}); - return this.parseOrder (data); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'fetchOpenOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - }; - const response = await this.accountCategoryGetOrderOpen (this.extend (request, params)); - // - // { - // "ac": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "code": 0, - // "data": [ - // { - // "avgPx": "0", // Average filled price of the order - // "cumFee": "0", // cumulative fee paid for this order - // "cumFilledQty": "0", // cumulative filled quantity - // "errorCode": "", // error code; could be empty - // "feeAsset": "USDT", // fee asset - // "lastExecTime": 1576019723550, // The last execution time of the order - // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId - // "orderQty": "0.0083", // order quantity - // "orderType": "Limit", // order type - // "price": "7105", // order price - // "seqNum": 8193258, // sequence number - // "side": "Buy", // order side - // "status": "New", // order status on matching engine - // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty - // "symbol": "BTC/USDT", - // "execInst": "NULL_VAL" // execution instruction - // }, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - if (accountCategory === 'futures') { - return this.parseOrders (data, market, since, limit); - } - // a workaround for https://github.com/ccxt/ccxt/issues/7187 - const orders = []; - for (let i = 0; i < data.length; i++) { - const order = this.parseOrder (data[i], market); - orders.push (order); - } - return this.filterBySymbolSinceLimit (orders, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - const defaultAccountCategory = this.safeString (this.options, 'account-category'); - const options = this.safeValue (this.options, 'fetchClosedOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - // 'category': accountCategory, - // 'symbol': market['id'], - // 'orderType': 'market', // optional, string - // 'side': 'buy', // or 'sell', optional, case insensitive. - // 'status': 'Filled', // "Filled", "Canceled", or "Rejected" - // 'startTime': exchange.milliseconds (), - // 'endTime': exchange.milliseconds (), - // 'page': 1, - // 'pageSize': 100, - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['symbol'] = market['id']; - } - const method = this.safeValue (options, 'method', 'accountGroupGetOrderHist'); - if (method === 'accountGroupGetOrderHist') { - if (accountCategory !== undefined) { - request['category'] = accountCategory; - } - } else { - request['account-category'] = accountCategory; - } - if (since !== undefined) { - request['startTime'] = since; - } - if (limit !== undefined) { - request['pageSize'] = limit; - } - const response = await this[method] (this.extend (request, params)); - // - // accountCategoryGetOrderHistCurrent - // - // { - // "code":0, - // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda", - // "ac":"CASH", - // "data":[ - // { - // "seqNum":15561826728, - // "orderId":"a17294d305c0U6491137460bethu7kw9", - // "symbol":"ETH/USDT", - // "orderType":"Limit", - // "lastExecTime":1591635618200, - // "price":"200", - // "orderQty":"0.1", - // "side":"Buy", - // "status":"Canceled", - // "avgPx":"0", - // "cumFilledQty":"0", - // "stopPrice":"", - // "errorCode":"", - // "cumFee":"0", - // "feeAsset":"USDT", - // "execInst":"NULL_VAL" - // } - // ] - // } - // - // accountGroupGetOrderHist - // - // { - // "code": 0, - // "data": { - // "data": [ - // { - // "ac": "FUTURES", - // "accountId": "testabcdefg", - // "avgPx": "0", - // "cumFee": "0", - // "cumQty": "0", - // "errorCode": "NULL_VAL", - // "execInst": "NULL_VAL", - // "feeAsset": "USDT", - // "lastExecTime": 1584072844085, - // "orderId": "r170d21956dd5450276356bbtcpKa74", - // "orderQty": "1.1499", - // "orderType": "Limit", - // "price": "4000", - // "sendingTime": 1584072841033, - // "seqNum": 24105338, - // "side": "Buy", - // "status": "Canceled", - // "stopPrice": "", - // "symbol": "BTC-PERP" - // }, - // ], - // "hasNext": False, - // "limit": 500, - // "page": 1, - // "pageSize": 20 - // } - // } - // - let data = this.safeValue (response, 'data'); - const isArray = Array.isArray (data); - if (!isArray) { - data = this.safeValue (data, 'data', []); - } - return this.parseOrders (data, market, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument'); - } - await this.loadMarkets (); - await this.loadAccounts (); - const market = this.market (symbol); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'cancelOrder', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'symbol': market['id'], - 'time': this.milliseconds (), - 'id': 'foobar', - }; - if (clientOrderId === undefined) { - request['orderId'] = id; - } else { - request['id'] = clientOrderId; - params = this.omit (params, [ 'clientOrderId', 'id' ]); - } - const response = await this.accountCategoryDeleteOrder (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "ac": "CASH", - // "action": "cancel-order", - // "status": "Ack", - // "info": { - // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23", - // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc", - // "orderType": "", // could be empty - // "symbol": "ETH/USDT", - // "timestamp": 1573594877822 - // } - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const info = this.safeValue (data, 'info', {}); - return this.parseOrder (info, market); - } - - async cancelAllOrders (symbol = undefined, params = {}) { - await this.loadMarkets (); - await this.loadAccounts (); - const defaultAccountCategory = this.safeString (this.options, 'account-category', 'cash'); - const options = this.safeValue (this.options, 'cancelAllOrders', {}); - let accountCategory = this.safeString (options, 'account-category', defaultAccountCategory); - accountCategory = this.safeString (params, 'account-category', accountCategory); - params = this.omit (params, 'account-category'); - const account = this.safeValue (this.accounts, 0, {}); - const accountGroup = this.safeValue (account, 'id'); - const request = { - 'account-group': accountGroup, - 'account-category': accountCategory, - 'time': this.milliseconds (), - }; - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - request['symbol'] = market['id']; - } - const response = await this.accountCategoryDeleteOrderAll (this.extend (request, params)); - // - // { - // "code": 0, - // "data": { - // "ac": "CASH", - // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo", - // "action": "cancel-all", - // "info": { - // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy", - // "orderId": "", - // "orderType": "NULL_VAL", - // "symbol": "", - // "timestamp": 1574118495462 - // }, - // "status": "Ack" - // } - // } - // - return response; - } - - parseDepositAddress (depositAddress, currency = undefined) { - // - // { - // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // destTag: "", - // tagType: "", - // tagId: "", - // chainName: "ERC20", - // numConfirmations: 20, - // withdrawalFee: 1, - // nativeScale: 4, - // tips: [] - // } - // - const address = this.safeString (depositAddress, 'address'); - const tagId = this.safeString (depositAddress, 'tagId'); - const tag = this.safeString (depositAddress, tagId); - this.checkAddress (address); - const code = (currency === undefined) ? undefined : currency['code']; - return { - 'currency': code, - 'address': address, - 'tag': tag, - 'info': depositAddress, - }; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const chainName = this.safeString (params, 'chainName'); - params = this.omit (params, 'chainName'); - const request = { - 'asset': currency['id'], - }; - const response = await this.privateGetWalletDepositAddress (this.extend (request, params)); - // - // { - // "code":0, - // "data":{ - // "asset":"USDT", - // "assetName":"Tether", - // "address":[ - // { - // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6", - // "destTag":"", - // "tagType":"", - // "tagId":"", - // "chainName":"Omni", - // "numConfirmations":3, - // "withdrawalFee":4.7, - // "nativeScale":4, - // "tips":[] - // }, - // { - // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // "destTag":"", - // "tagType":"", - // "tagId":"", - // "chainName":"ERC20", - // "numConfirmations":20, - // "withdrawalFee":1.0, - // "nativeScale":4, - // "tips":[] - // } - // ] - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const addresses = this.safeValue (data, 'address', []); - const numAddresses = addresses.length; - let address = undefined; - if (numAddresses > 1) { - const addressesByChainName = this.indexBy (addresses, 'chainName'); - if (chainName === undefined) { - const chainNames = Object.keys (addressesByChainName); - const chains = chainNames.join (', '); - throw new ArgumentsRequired (this.id + ' fetchDepositAddress returned more than one address, a chainName parameter is required, one of ' + chains); - } - address = this.safeValue (addressesByChainName, chainName, {}); - } else { - // first address - address = this.safeValue (addresses, 0, {}); - } - const result = this.parseDepositAddress (address, currency); - return this.extend (result, { - 'info': response, - }); - } - - async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { - const request = { - 'txType': 'deposit', - }; - return await this.fetchTransactions (code, since, limit, this.extend (request, params)); - } - - async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { - const request = { - 'txType': 'withdrawal', - }; - return await this.fetchTransactions (code, since, limit, this.extend (request, params)); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'asset': currency['id'], - // 'page': 1, - // 'pageSize': 20, - // 'startTs': this.milliseconds (), - // 'endTs': this.milliseconds (), - // 'txType': undefned, // deposit, withdrawal - }; - let currency = undefined; - if (code !== undefined) { - currency = this.currency (code); - request['asset'] = currency['id']; - } - if (since !== undefined) { - request['startTs'] = since; - } - if (limit !== undefined) { - request['pageSize'] = limit; - } - const response = await this.privateGetWalletTransactions (this.extend (request, params)); - // - // { - // code: 0, - // data: { - // data: [ - // { - // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", - // time: 1591606166000, - // asset: "USDT", - // transactionType: "deposit", - // amount: "25", - // commission: "0", - // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", - // status: "pending", - // numConfirmed: 8, - // numConfirmations: 20, - // destAddress: { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" } - // } - // ], - // page: 1, - // pageSize: 20, - // hasNext: false - // } - // } - // - const data = this.safeValue (response, 'data', {}); - const transactions = this.safeValue (data, 'data', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - 'reviewing': 'pending', - 'pending': 'pending', - 'confirmed': 'ok', - 'rejected': 'rejected', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB", - // time: 1591606166000, - // asset: "USDT", - // transactionType: "deposit", - // amount: "25", - // commission: "0", - // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce", - // status: "pending", - // numConfirmed: 8, - // numConfirmations: 20, - // destAddress: { - // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722", - // destTag: "..." // for currencies that have it - // } - // } - // - const id = this.safeString (transaction, 'requestId'); - const amount = this.safeFloat (transaction, 'amount'); - const destAddress = this.safeValue (transaction, 'destAddress', {}); - const address = this.safeString (destAddress, 'address'); - const tag = this.safeString (destAddress, 'destTag'); - const txid = this.safeString (transaction, 'networkTransactionId'); - const type = this.safeString (transaction, 'transactionType'); - const timestamp = this.safeInteger (transaction, 'time'); - const currencyId = this.safeString (transaction, 'asset'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'commission'); - return { - 'info': transaction, - 'id': id, - 'currency': code, - 'amount': amount, - 'address': address, - 'addressTo': address, - 'addressFrom': undefined, - 'tag': tag, - 'tagTo': tag, - 'tagFrom': undefined, - 'status': status, - 'type': type, - 'updated': undefined, - 'txid': txid, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'fee': { - 'currency': code, - 'cost': feeCost, - }, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = ''; - let query = params; - const accountCategory = (api === 'accountCategory'); - if (accountCategory || (api === 'accountGroup')) { - url += this.implodeParams ('/{account-group}', params); - query = this.omit (params, 'account-group'); - } - const request = this.implodeParams (path, query); - url += '/api/pro/' + this.version; - if (accountCategory) { - url += this.implodeParams ('/{account-category}', query); - query = this.omit (query, 'account-category'); - } - url += '/' + request; - query = this.omit (query, this.extractParams (path)); - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const timestamp = this.milliseconds ().toString (); - const payload = timestamp + '+' + request; - const hmac = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64'); - headers = { - 'x-auth-key': this.apiKey, - 'x-auth-timestamp': timestamp, - 'x-auth-signature': hmac, - }; - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - headers['Content-Type'] = 'application/json'; - body = this.json (query); - } - } - url = this.urls['api'] + url; - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - // - // {'code': 6010, 'message': 'Not enough balance.'} - // {'code': 60060, 'message': 'The order is already filled or canceled.'} - // {"code":2100,"message":"ApiKeyFailure"} - // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}} - // - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'message'); - const error = (code !== undefined) && (code !== '0'); - if (error || (message !== undefined)) { - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],38:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],38:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -26373,6 +26421,7 @@ module.exports = class bitmax extends Exchange { const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, BadRequest, DDoSProtection, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -26583,8 +26632,8 @@ module.exports = class bitmex extends Exchange { 'amount': undefined, 'price': undefined, }; - const lotSize = this.safeFloat (market, 'lotSize'); - const tickSize = this.safeFloat (market, 'tickSize'); + const lotSize = this.safeNumber (market, 'lotSize'); + const tickSize = this.safeNumber (market, 'tickSize'); if (lotSize !== undefined) { precision['amount'] = lotSize; } @@ -26598,7 +26647,7 @@ module.exports = class bitmex extends Exchange { }, 'price': { 'min': tickSize, - 'max': this.safeFloat (market, 'maxPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { 'min': undefined, @@ -26608,7 +26657,7 @@ module.exports = class bitmex extends Exchange { const limitField = (position === quote) ? 'cost' : 'amount'; limits[limitField] = { 'min': lotSize, - 'max': this.safeFloat (market, 'maxOrderQty'), + 'max': this.safeNumber (market, 'maxOrderQty'), }; result.push ({ 'id': id, @@ -26620,8 +26669,8 @@ module.exports = class bitmex extends Exchange { 'active': active, 'precision': precision, 'limits': limits, - 'taker': this.safeFloat (market, 'takerFee'), - 'maker': this.safeFloat (market, 'makerFee'), + 'taker': this.safeNumber (market, 'takerFee'), + 'maker': this.safeNumber (market, 'makerFee'), 'type': type, 'spot': false, 'swap': swap, @@ -26687,21 +26736,17 @@ module.exports = class bitmex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - let free = this.safeFloat (balance, 'availableMargin'); - let total = this.safeFloat (balance, 'marginBalance'); + let free = this.safeString (balance, 'availableMargin'); + let total = this.safeString (balance, 'marginBalance'); if (code === 'BTC') { - if (free !== undefined) { - free /= 100000000; - } - if (total !== undefined) { - total /= 100000000; - } + free = Precise.stringDiv (free, '1e8'); + total = Precise.stringDiv (total, '1e8'); } account['free'] = free; account['total'] = total; result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -26780,8 +26825,8 @@ module.exports = class bitmex extends Exchange { for (let i = 0; i < response.length; i++) { const order = response[i]; const side = (order['side'] === 'Sell') ? 'asks' : 'bids'; - const amount = this.safeFloat (order, 'size'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const price = this.safeNumber (order, 'price'); // https://github.com/ccxt/ccxt/issues/4926 // https://github.com/ccxt/ccxt/issues/4927 // the exchange sometimes returns null price in the orderbook @@ -26987,7 +27032,7 @@ module.exports = class bitmex extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'transactType')); const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount !== undefined) { amount = amount / 100000000; } @@ -26998,7 +27043,7 @@ module.exports = class bitmex extends Exchange { // for unrealized pnl and other transactions without a timestamp timestamp = 0; // see comments above } - let feeCost = this.safeFloat (item, 'fee', 0); + let feeCost = this.safeNumber (item, 'fee', 0); if (feeCost !== undefined) { feeCost = feeCost / 100000000; } @@ -27006,7 +27051,7 @@ module.exports = class bitmex extends Exchange { 'cost': feeCost, 'currency': code, }; - let after = this.safeFloat (item, 'walletBalance'); + let after = this.safeNumber (item, 'walletBalance'); if (after !== undefined) { after = after / 100000000; } @@ -27325,8 +27370,8 @@ module.exports = class bitmex extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const open = this.safeFloat (ticker, 'prevPrice24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'prevPrice24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; if (last !== undefined && open !== undefined) { @@ -27339,13 +27384,13 @@ module.exports = class bitmex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askPrice'), + 'ask': this.safeNumber (ticker, 'askPrice'), 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'vwap'), + 'vwap': this.safeNumber (ticker, 'vwap'), 'open': open, 'close': last, 'last': last, @@ -27353,8 +27398,8 @@ module.exports = class bitmex extends Exchange { 'change': change, 'percentage': percentage, 'average': this.sum (open, last) / 2, - 'baseVolume': this.safeFloat (ticker, 'homeNotional24h'), - 'quoteVolume': this.safeFloat (ticker, 'foreignNotional24h'), + 'baseVolume': this.safeNumber (ticker, 'homeNotional24h'), + 'quoteVolume': this.safeNumber (ticker, 'foreignNotional24h'), 'info': ticker, }; } @@ -27379,11 +27424,11 @@ module.exports = class bitmex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -27512,23 +27557,23 @@ module.exports = class bitmex extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat2 (trade, 'avgPx', 'price'); - const amount = this.safeFloat2 (trade, 'size', 'lastQty'); + const price = this.safeNumber2 (trade, 'avgPx', 'price'); + const amount = this.safeNumber2 (trade, 'size', 'lastQty'); const id = this.safeString (trade, 'trdMatchID'); const order = this.safeString (trade, 'orderID'); const side = this.safeStringLower (trade, 'side'); // price * amount doesn't work for all symbols (e.g. XBT, ETH) - let cost = this.safeFloat (trade, 'execCost'); + let cost = this.safeNumber (trade, 'execCost'); if (cost !== undefined) { cost = Math.abs (cost) / 100000000; } let fee = undefined; if ('execComm' in trade) { - let feeCost = this.safeFloat (trade, 'execComm'); + let feeCost = this.safeNumber (trade, 'execComm'); feeCost = feeCost / 100000000; const currencyId = this.safeString (trade, 'settlCurrency'); const feeCurrency = this.safeCurrencyCode (currencyId); - const feeRate = this.safeFloat (trade, 'commission'); + const feeRate = this.safeNumber (trade, 'commission'); fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -27630,33 +27675,19 @@ module.exports = class bitmex extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'transactTime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty', 0.0); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (amount - filled, 0.0); - } - } - const average = this.safeFloat (order, 'avgPx'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = average * filled; - } else if (price !== undefined) { - cost = price * filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty', 0.0); + const average = this.safeNumber (order, 'avgPx'); const id = this.safeString (order, 'orderID'); const type = this.safeStringLower (order, 'ordType'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'clOrdID'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'ParticipateDoNotInitiate'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -27671,14 +27702,14 @@ module.exports = class bitmex extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { @@ -27739,7 +27770,7 @@ module.exports = class bitmex extends Exchange { 'ordType': orderType, }; if ((orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched')) { - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPx or stopPrice parameter for the ' + orderType + ' order type'); } else { @@ -27856,7 +27887,7 @@ module.exports = class bitmex extends Exchange { return this.parseOrders (response, market); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPosition (params); // [ @@ -28051,7 +28082,7 @@ module.exports = class bitmex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],39:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],39:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -28382,7 +28413,7 @@ module.exports = class bitpanda extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; @@ -28455,9 +28486,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -28504,8 +28535,8 @@ module.exports = class bitpanda extends Exchange { const activeFeeTier = this.safeValue (response, 'active_fee_tier', {}); const result = { 'info': response, - 'maker': this.safeFloat (activeFeeTier, 'maker_fee'), - 'taker': this.safeFloat (activeFeeTier, 'taker_fee'), + 'maker': this.safeNumber (activeFeeTier, 'maker_fee'), + 'taker': this.safeNumber (activeFeeTier, 'taker_fee'), 'percentage': true, 'tierBased': true, }; @@ -28514,9 +28545,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -28554,27 +28585,27 @@ module.exports = class bitpanda extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last_price'); - const percentage = this.safeFloat (ticker, 'price_change_percentage'); - const change = this.safeFloat (ticker, 'price_change'); + const last = this.safeNumber (ticker, 'last_price'); + const percentage = this.safeNumber (ticker, 'price_change_percentage'); + const change = this.safeNumber (ticker, 'price_change'); let open = undefined; let average = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'best_bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -28759,11 +28790,11 @@ module.exports = class bitpanda extends Exchange { const volumeField = this.safeString (options, 'volume', 'total_amount'); return [ alignedTimestamp, - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -28849,21 +28880,21 @@ module.exports = class bitpanda extends Exchange { timestamp = this.parse8601 (this.safeString (trade, 'time')); } const side = this.safeStringLower2 (trade, 'side', 'taker_side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + let cost = this.safeNumber (trade, 'volume'); if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { cost = amount * price; } const marketId = this.safeString (trade, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (feeInfo, 'fee_amount'); + const feeCost = this.safeNumber (feeInfo, 'fee_amount'); let takerOrMaker = undefined; let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (feeInfo, 'fee_percentage'); + const feeRate = this.safeNumber (feeInfo, 'fee_percentage'); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, @@ -28946,11 +28977,11 @@ module.exports = class bitpanda extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -29204,12 +29235,12 @@ module.exports = class bitpanda extends Exchange { // } // const id = this.safeString (transaction, 'transaction_id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const currencyId = this.safeString (transaction, 'currency'); currency = this.safeCurrency (currencyId, currency); const status = 'ok'; // the exchange returns cleared transactions only - const feeCost = this.safeFloat2 (transaction, 'fee_amount', 'fee'); + const feeCost = this.safeNumber2 (transaction, 'fee_amount', 'fee'); let fee = undefined; const addressTo = this.safeString (transaction, 'recipient'); const tagTo = this.safeString (transaction, 'destination_tag'); @@ -29324,72 +29355,34 @@ module.exports = class bitpanda extends Exchange { // ] // } // - const rawTrades = this.safeValue (order, 'trades', []); - order = this.safeValue (order, 'order', order); - const id = this.safeString (order, 'order_id'); - const clientOrderId = this.safeString (order, 'client_id'); - const timestamp = this.parse8601 (this.safeString (order, 'time')); - let status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'instrument_code'); + const rawOrder = this.safeValue (order, 'order', order); + const id = this.safeString (rawOrder, 'order_id'); + const clientOrderId = this.safeString (rawOrder, 'client_id'); + const timestamp = this.parse8601 (this.safeString (rawOrder, 'time')); + const rawStatus = this.parseOrderStatus (this.safeString (rawOrder, 'status')); + const status = this.parseOrderStatus (rawStatus); + const marketId = this.safeString (rawOrder, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - if (status === undefined) { - if (remaining > 0) { - status = 'open'; - } else { - status = 'closed'; - } - } - } - } - const side = this.safeStringLower (order, 'side'); - const type = this.safeStringLower (order, 'type'); - const trades = this.parseTrades (rawTrades, market, undefined, undefined); - const fees = []; - const numTrades = trades.length; - let lastTradeTimestamp = undefined; - let tradeCost = undefined; - let tradeAmount = undefined; - if (numTrades > 0) { - lastTradeTimestamp = trades[0]['timestamp']; - tradeCost = 0; - tradeAmount = 0; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - fees.push (trade['fee']); - lastTradeTimestamp = Math.max (lastTradeTimestamp, trade['timestamp']); - tradeCost = this.sum (tradeCost, trade['cost']); - tradeAmount = this.sum (tradeAmount, trade['amount']); - } - } - let average = this.safeFloat (order, 'average_price'); - if (average === undefined) { - if ((tradeCost !== undefined) && (tradeAmount !== undefined) && (tradeAmount !== 0)) { - average = tradeCost / tradeAmount; - } - } - if (cost === undefined) { - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - } - const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'trigger_price'); - const postOnly = this.safeValue (order, 'is_post_only'); - const result = { + const price = this.safeNumber (rawOrder, 'price'); + const amount = this.safeNumber (rawOrder, 'amount'); + const filledString = this.safeString (rawOrder, 'filled_amount'); + const filled = this.parseNumber (filledString); + const side = this.safeStringLower (rawOrder, 'side'); + const type = this.safeStringLower (rawOrder, 'type'); + const timeInForce = this.parseTimeInForce (this.safeString (rawOrder, 'time_in_force')); + const stopPrice = this.safeNumber (rawOrder, 'trigger_price'); + const postOnly = this.safeValue (rawOrder, 'is_post_only'); + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'type': type, + }); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -29398,41 +29391,14 @@ module.exports = class bitpanda extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, // 'fee': undefined, 'trades': trades, - }; - const numFees = fees.length; - if (numFees > 0) { - if (numFees === 1) { - result['fee'] = fees[0]; - } else { - const feesByCurrency = this.groupBy (fees, 'currency'); - const feeCurrencies = Object.keys (feesByCurrency); - const numFeesByCurrency = feeCurrencies.length; - if (numFeesByCurrency === 1) { - const feeCurrency = feeCurrencies[0]; - const feeArray = this.safeValue (feesByCurrency, feeCurrency); - let feeCost = 0; - for (let i = 0; i < feeArray.length; i++) { - feeCost = this.sum (feeCost, feeArray[i]['cost']); - } - result['fee'] = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } else { - result['fees'] = fees; - } - } - } else { - result['fee'] = undefined; - } - return result; + }); } parseTimeInForce (timeInForce) { @@ -29466,7 +29432,7 @@ module.exports = class bitpanda extends Exchange { priceIsRequired = true; } if (uppercaseType === 'STOP') { - const triggerPrice = this.safeFloat (params, 'trigger_price'); + const triggerPrice = this.safeNumber (params, 'trigger_price'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a trigger_price param for ' + type + ' orders'); } @@ -29869,7 +29835,7 @@ module.exports = class bitpanda extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],40:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],40:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -30029,28 +29995,28 @@ module.exports = class bitso extends Exchange { const symbol = base + '/' + quote; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), - 'max': this.safeFloat (market, 'maximum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), + 'max': this.safeNumber (market, 'maximum_amount'), }, 'price': { - 'min': this.safeFloat (market, 'minimum_price'), - 'max': this.safeFloat (market, 'maximum_price'), + 'min': this.safeNumber (market, 'minimum_price'), + 'max': this.safeNumber (market, 'maximum_price'), }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), - 'max': this.safeFloat (market, 'maximum_value'), + 'min': this.safeNumber (market, 'minimum_value'), + 'max': this.safeNumber (market, 'maximum_value'), }, }; - const defaultPricePrecision = this.safeFloat (this.options['precision'], quote, this.options['defaultPrecision']); - const pricePrecision = this.safeFloat (market, 'tick_size', defaultPricePrecision); + const defaultPricePrecision = this.safeNumber (this.options['precision'], quote, this.options['defaultPrecision']); + const pricePrecision = this.safeNumber (market, 'tick_size', defaultPricePrecision); const precision = { - 'amount': this.safeFloat (this.options['precision'], base, this.options['defaultPrecision']), + 'amount': this.safeNumber (this.options['precision'], base, this.options['defaultPrecision']), 'price': pricePrecision, }; const fees = this.safeValue (market, 'fees', {}); const flatRate = this.safeValue (fees, 'flat_rate', {}); - const maker = this.safeFloat (flatRate, 'maker'); - const taker = this.safeFloat (flatRate, 'taker'); + const maker = this.safeNumber (flatRate, 'maker'); + const taker = this.safeNumber (flatRate, 'taker'); const feeTiers = this.safeValue (fees, 'structure', []); const fee = { 'taker': parseFloat (this.decimalToPrecision (taker / 100, ROUND, 0.00000001, TICK_SIZE)), @@ -30062,9 +30028,9 @@ module.exports = class bitso extends Exchange { const makerFees = []; for (let j = 0; j < feeTiers.length; j++) { const tier = feeTiers[j]; - const volume = this.safeFloat (tier, 'volume'); - const takerFee = this.safeFloat (tier, 'taker'); - const makerFee = this.safeFloat (tier, 'maker'); + const volume = this.safeNumber (tier, 'volume'); + const takerFee = this.safeNumber (tier, 'taker'); + const makerFee = this.safeNumber (tier, 'maker'); const takerFeeToPrecision = parseFloat (this.decimalToPrecision (takerFee / 100, ROUND, 0.00000001, TICK_SIZE)); const makerFeeToPrecision = parseFloat (this.decimalToPrecision (makerFee / 100, ROUND, 0.00000001, TICK_SIZE)); takerFees.push ([ volume, takerFeeToPrecision ]); @@ -30104,14 +30070,13 @@ module.exports = class bitso extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'locked'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -30133,22 +30098,22 @@ module.exports = class bitso extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'payload'); const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -30169,12 +30134,12 @@ module.exports = class bitso extends Exchange { const marketId = this.safeString (trade, 'book'); const symbol = this.safeSymbol (marketId, market, '_'); const side = this.safeString2 (trade, 'side', 'maker_side'); - let amount = this.safeFloat2 (trade, 'amount', 'major'); + let amount = this.safeNumber2 (trade, 'amount', 'major'); if (amount !== undefined) { amount = Math.abs (amount); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fees_amount'); + const feeCost = this.safeNumber (trade, 'fees_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fees_currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -30183,11 +30148,11 @@ module.exports = class bitso extends Exchange { 'currency': feeCurrency, }; } - let cost = this.safeFloat (trade, 'minor'); + let cost = this.safeNumber (trade, 'minor'); if (cost !== undefined) { cost = Math.abs (cost); } - const price = this.safeFloat (trade, 'price'); + const price = this.safeNumber (trade, 'price'); const orderId = this.safeString (trade, 'oid'); const id = this.safeString (trade, 'tid'); return { @@ -30288,17 +30253,11 @@ module.exports = class bitso extends Exchange { const symbol = this.safeSymbol (marketId, market, '_'); const orderType = this.safeString (order, 'type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'unfilled_amount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'unfilled_amount'); const clientOrderId = this.safeString (order, 'client_id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -30315,12 +30274,12 @@ module.exports = class bitso extends Exchange { 'amount': amount, 'cost': undefined, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = 25, params = {}) { @@ -30496,7 +30455,7 @@ module.exports = class bitso extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],41:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],41:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -30614,6 +30573,16 @@ module.exports = class bitstamp extends Exchange { 'usdc_address/', 'omg_withdrawal/', 'omg_address/', + 'dai_withdrawal/', + 'dai_address/', + 'knc_withdrawal/', + 'knc_address/', + 'mkr_withdrawal/', + 'mkr_address/', + 'zrx_withdrawal/', + 'zrx_address/', + 'gusd_withdrawal/', + 'gusd_address/', 'transfer-to-main/', 'transfer-from-main/', 'withdrawal-requests/', @@ -30748,13 +30717,15 @@ module.exports = class bitstamp extends Exchange { const symbolId = baseId + '_' + quoteId; const id = this.safeString (market, 'url_symbol'); const precision = { - 'amount': market['base_decimals'], - 'price': market['counter_decimals'], + 'amount': this.safeInteger (market, 'base_decimals'), + 'price': this.safeInteger (market, 'counter_decimals'), }; - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; // let [ cost, currency ] = market['minimum_order'].split (' '); - const active = (market['trading'] === 'Enabled'); + const trading = this.safeString (market, 'trading'); + const active = (trading === 'Enabled'); result.push ({ 'id': id, 'symbol': symbol, @@ -30798,7 +30769,7 @@ module.exports = class bitstamp extends Exchange { 'type': currencyType, 'name': name, 'active': true, - 'fee': this.safeFloat (description['fees']['funding']['withdraw'], code), + 'fee': this.safeNumber (description['fees']['funding']['withdraw'], code), 'precision': precision, 'limits': { 'amount': { @@ -30851,13 +30822,16 @@ module.exports = class bitstamp extends Exchange { quote = this.safeCurrencyCode (quote); const description = this.safeString (market, 'description'); const [ baseDescription, quoteDescription ] = description.split (' / '); - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; if (!(base in result)) { - result[base] = this.constructCurrencyObject (baseId, base, baseDescription, market['base_decimals'], undefined, market); + const baseDecimals = this.safeInteger (market, 'base_decimals'); + result[base] = this.constructCurrencyObject (baseId, base, baseDescription, baseDecimals, undefined, market); } if (!(quote in result)) { - result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, market['counter_decimals'], parseFloat (cost), market); + const counterDecimals = this.safeInteger (market, 'counter_decimals'); + result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, counterDecimals, parseFloat (cost), market); } } return result; @@ -30899,25 +30873,25 @@ module.exports = class bitstamp extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -30960,7 +30934,7 @@ module.exports = class bitstamp extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; if (id.indexOf ('_') < 0) { - const value = this.safeFloat (transaction, id); + const value = this.safeNumber (transaction, id); if ((value !== undefined) && (value !== 0)) { return id; } @@ -31042,11 +31016,11 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString2 (trade, 'id', 'tid'); let symbol = undefined; let side = undefined; - let price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat (trade, 'amount'); + let price = this.safeNumber (trade, 'price'); + let amount = this.safeNumber (trade, 'amount'); const orderId = this.safeString (trade, 'order_id'); const type = undefined; - let cost = this.safeFloat (trade, 'cost'); + let cost = this.safeNumber (trade, 'cost'); if (market === undefined) { const keys = Object.keys (trade); for (let i = 0; i < keys.length; i++) { @@ -31063,12 +31037,12 @@ module.exports = class bitstamp extends Exchange { market = this.getMarketFromTrade (trade); } } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = undefined; if (market !== undefined) { - price = this.safeFloat (trade, market['symbolId'], price); - amount = this.safeFloat (trade, market['baseId'], amount); - cost = this.safeFloat (trade, market['quoteId'], cost); + price = this.safeNumber (trade, market['symbolId'], price); + amount = this.safeNumber (trade, market['baseId'], amount); + cost = this.safeNumber (trade, market['quoteId'], cost); feeCurrency = market['quote']; symbol = market['symbol']; } @@ -31137,7 +31111,7 @@ module.exports = class bitstamp extends Exchange { parseTradingFee (balances, symbol) { const market = this.market (symbol); - const tradeFee = this.safeFloat (balances, market['id'] + '_fee'); + const tradeFee = this.safeNumber (balances, market['id'] + '_fee'); return { 'symbol': symbol, 'maker': tradeFee, @@ -31187,11 +31161,11 @@ module.exports = class bitstamp extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -31249,12 +31223,12 @@ module.exports = class bitstamp extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -31301,7 +31275,7 @@ module.exports = class bitstamp extends Exchange { if (id.indexOf ('_withdrawal_fee') >= 0) { const currencyId = id.split ('_')[0]; const code = this.safeCurrencyCode (currencyId); - withdraw[code] = this.safeFloat (balance, id); + withdraw[code] = this.safeNumber (balance, id); } } return { @@ -31547,16 +31521,16 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString (transaction, 'id'); const currencyId = this.getCurrencyIdFromTransaction (transaction); const code = this.safeCurrencyCode (currencyId, currency); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let feeCurrency = undefined; let amount = undefined; if ('amount' in transaction) { - amount = this.safeFloat (transaction, 'amount'); + amount = this.safeNumber (transaction, 'amount'); } else if (currency !== undefined) { - amount = this.safeFloat (transaction, currency['id'], amount); + amount = this.safeNumber (transaction, currency['id'], amount); feeCurrency = currency['code']; } else if ((code !== undefined) && (currencyId !== undefined)) { - amount = this.safeFloat (transaction, currencyId, amount); + amount = this.safeNumber (transaction, currencyId, amount); feeCurrency = code; } if (amount !== undefined) { @@ -31681,83 +31655,23 @@ module.exports = class bitstamp extends Exchange { } // there is no timestamp from fetchOrder const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - let lastTradeTimestamp = undefined; - let symbol = undefined; - let marketId = this.safeStringLower (order, 'currency_pair'); - if (marketId !== undefined) { - marketId = marketId.replace ('/', ''); - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - symbol = market['symbol']; - } - } - let amount = this.safeFloat (order, 'amount'); - let filled = 0.0; - const trades = []; - const transactions = this.safeValue (order, 'transactions', []); - let feeCost = undefined; - let cost = undefined; - const numTransactions = transactions.length; - if (numTransactions > 0) { - feeCost = 0.0; - for (let i = 0; i < numTransactions; i++) { - const trade = this.parseTrade (this.extend ({ - 'order_id': id, - 'side': side, - }, transactions[i]), market); - filled = this.sum (filled, trade['amount']); - feeCost = this.sum (feeCost, trade['fee']['cost']); - if (cost === undefined) { - cost = 0.0; - } - cost = this.sum (cost, trade['cost']); - trades.push (trade); - } - lastTradeTimestamp = trades[numTransactions - 1]['timestamp']; - } + const marketId = this.safeStringLower (order, 'currency_pair'); + let symbol = this.safeSymbol (marketId, market, '/'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((status === 'closed') && (amount === undefined)) { - amount = filled; + const amount = this.safeNumber (order, 'amount'); + const transactions = this.safeValue (order, 'transactions', []); + const trades = this.parseTrades (transactions, market); + const length = trades.length; + if (length) { + symbol = trades[0]['symbol']; } - let remaining = undefined; - if (amount !== undefined) { - remaining = amount - filled; - } - let price = this.safeFloat (order, 'price'); - if (market === undefined) { - market = this.getMarketFromTrades (trades); - } - let feeCurrency = undefined; - if (market !== undefined) { - if (symbol === undefined) { - symbol = market['symbol']; - } - feeCurrency = market['quote']; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if (price === undefined) { - if (filled > 0) { - price = cost / filled; - } - } - let fee = undefined; - if (feeCost !== undefined) { - if (feeCurrency !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { + const price = this.safeNumber (order, 'price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'status': status, 'symbol': symbol, 'type': undefined, @@ -31766,15 +31680,15 @@ module.exports = class bitstamp extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, - 'filled': filled, - 'remaining': remaining, + 'filled': undefined, + 'remaining': undefined, 'trades': trades, - 'fee': fee, + 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } parseLedgerEntryType (type) { @@ -31854,11 +31768,11 @@ module.exports = class bitstamp extends Exchange { const parsedTransaction = this.parseTransaction (item); let direction = undefined; if ('amount' in item) { - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); direction = amount > 0 ? 'in' : 'out'; } else if (('currency' in parsedTransaction) && parsedTransaction['currency'] !== undefined) { const currencyId = this.currencyId (parsedTransaction['currency']); - const amount = this.safeFloat (item, currencyId); + const amount = this.safeNumber (item, currencyId); direction = amount > 0 ? 'in' : 'out'; } return { @@ -32105,13 +32019,14 @@ module.exports = class bitstamp extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],42:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],42:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -32208,25 +32123,25 @@ module.exports = class bitstamp1 extends Exchange { await this.loadMarkets (); const ticker = await this.publicGetTicker (params); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -32249,14 +32164,11 @@ module.exports = class bitstamp1 extends Exchange { } } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -32300,12 +32212,12 @@ module.exports = class bitstamp1 extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -32406,7 +32318,7 @@ module.exports = class bitstamp1 extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],43:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],43:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -32414,6 +32326,7 @@ module.exports = class bitstamp1 extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, DDoSProtection, PermissionDenied, AddressPending, OnMaintenance, BadRequest, InvalidAddress } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -32689,7 +32602,7 @@ module.exports = class bittrex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeSize'), + 'min': this.safeNumber (market, 'minTradeSize'), 'max': undefined, }, 'price': { @@ -32717,11 +32630,11 @@ module.exports = class bittrex extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); const balance = indexed[currencyId]; - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -32781,7 +32694,7 @@ module.exports = class bittrex extends Exchange { const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); const precision = 8; // default precision, todo: fix "magic constants" - const fee = this.safeFloat (currency, 'txFee'); // todo: redesign + const fee = this.safeNumber (currency, 'txFee'); // todo: redesign const isActive = this.safeString (currency, 'status'); result[code] = { 'id': id, @@ -32842,17 +32755,17 @@ module.exports = class bittrex extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'updatedAt')); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const percentage = this.safeFloat (ticker, 'percentChange'); - const last = this.safeFloat (ticker, 'lastTradeRate'); + const percentage = this.safeNumber (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'lastTradeRate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidRate'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidRate'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askRate'), + 'ask': this.safeNumber (ticker, 'askRate'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -32862,8 +32775,8 @@ module.exports = class bittrex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -32976,21 +32889,18 @@ module.exports = class bittrex extends Exchange { const order = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'marketSymbol'); market = this.safeMarket (marketId, market, '-'); - let cost = undefined; - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'quantity'); - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = undefined; const isTaker = this.safeValue (trade, 'isTaker'); if (isTaker !== undefined) { takerOrMaker = isTaker ? 'taker' : 'maker'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -33060,11 +32970,11 @@ module.exports = class bittrex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'startsAt')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -33171,9 +33081,9 @@ module.exports = class bittrex extends Exchange { let cost = undefined; if (isCeilingLimit) { request['limit'] = this.priceToPrecision (symbol, price); - cost = this.safeFloat2 (params, 'ceiling', 'cost', amount); + cost = this.safeNumber2 (params, 'ceiling', 'cost', amount); } else if (isCeilingMarket) { - cost = this.safeFloat2 (params, 'ceiling', 'cost'); + cost = this.safeNumber2 (params, 'ceiling', 'cost'); if (cost === undefined) { if (price === undefined) { cost = amount; @@ -33332,7 +33242,7 @@ module.exports = class bittrex extends Exchange { // } // const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const address = this.safeString (transaction, 'cryptoAddress'); const txid = this.safeString (transaction, 'txId'); const updated = this.parse8601 (this.safeString (transaction, 'updatedAt')); @@ -33368,7 +33278,7 @@ module.exports = class bittrex extends Exchange { status = 'ok'; } } - let feeCost = this.safeFloat (transaction, 'txCost'); + let feeCost = this.safeNumber (transaction, 'txCost'); if (feeCost === undefined) { if (type === 'deposit') { // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge- @@ -33425,15 +33335,9 @@ module.exports = class bittrex extends Exchange { // } // const marketSymbol = this.safeString (order, 'marketSymbol'); - let symbol = undefined; - let feeCurrency = undefined; - if (marketSymbol !== undefined) { - const [ baseId, quoteId ] = marketSymbol.split ('-'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - feeCurrency = quote; - } + market = this.safeMarket (marketSymbol, market, '-'); + const symbol = market['symbol']; + const feeCurrency = market['quote']; const direction = this.safeStringLower (order, 'direction'); const createdAt = this.safeString (order, 'createdAt'); const updatedAt = this.safeString (order, 'updatedAt'); @@ -33446,32 +33350,15 @@ module.exports = class bittrex extends Exchange { } const timestamp = this.parse8601 (createdAt); const type = this.safeStringLower (order, 'type'); - const quantity = this.safeFloat (order, 'quantity'); - const limit = this.safeFloat (order, 'limit'); - const fillQuantity = this.safeFloat (order, 'fillQuantity'); - const commission = this.safeFloat (order, 'commission'); - const proceeds = this.safeFloat (order, 'proceeds'); - let average = undefined; - let remaining = undefined; - if (fillQuantity !== undefined) { - if (proceeds !== undefined) { - if (fillQuantity > 0) { - average = proceeds / fillQuantity; - } else if (proceeds === 0) { - average = 0; - } - } - if (quantity !== undefined) { - remaining = quantity - fillQuantity; - } - } - let status = this.safeStringLower (order, 'status'); - if ((status === 'closed') && (remaining !== undefined) && (remaining > 0)) { - status = 'canceled'; - } + const quantity = this.safeNumber (order, 'quantity'); + const limit = this.safeNumber (order, 'limit'); + const fillQuantity = this.safeNumber (order, 'fillQuantity'); + const commission = this.safeNumber (order, 'commission'); + const proceeds = this.safeNumber (order, 'proceeds'); + const status = this.safeStringLower (order, 'status'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'timestamp': timestamp, @@ -33485,10 +33372,10 @@ module.exports = class bittrex extends Exchange { 'price': limit, 'stopPrice': undefined, 'cost': proceeds, - 'average': average, + 'average': undefined, 'amount': quantity, 'filled': fillQuantity, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': { 'cost': commission, @@ -33496,7 +33383,7 @@ module.exports = class bittrex extends Exchange { }, 'info': order, 'trades': undefined, - }; + }); } parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { @@ -33545,9 +33432,9 @@ module.exports = class bittrex extends Exchange { 'side': this.safeString (order, 'side'), 'order': this.safeString (order, 'id'), 'type': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'average'), - 'amount': this.safeFloat (order, 'filled'), - 'cost': this.safeFloat (order, 'cost'), + 'price': this.safeNumber (order, 'average'), + 'amount': this.safeNumber (order, 'filled'), + 'cost': this.safeNumber (order, 'cost'), 'symbol': this.safeString (order, 'symbol'), 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -33839,7 +33726,7 @@ module.exports = class bittrex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],44:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],44:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -33847,6 +33734,7 @@ module.exports = class bittrex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -34148,7 +34036,7 @@ module.exports = class bitvavo extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minOrderInBaseAsset'), + 'min': this.safeNumber (market, 'minOrderInBaseAsset'), 'max': undefined, }, 'price': { @@ -34156,7 +34044,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderInQuoteAsset'), + 'min': this.safeNumber (market, 'minOrderInQuoteAsset'), 'max': undefined, }, }, @@ -34219,7 +34107,7 @@ module.exports = class bitvavo extends Exchange { 'code': code, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -34235,7 +34123,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMinAmount'), + 'min': this.safeNumber (currency, 'withdrawalMinAmount'), 'max': undefined, }, }, @@ -34292,14 +34180,14 @@ module.exports = class bitvavo extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); + const last = this.safeNumber (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -34311,12 +34199,12 @@ module.exports = class bitvavo extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': vwap, 'open': open, 'close': last, @@ -34332,14 +34220,6 @@ module.exports = class bitvavo extends Exchange { return result; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24h (params); @@ -34453,12 +34333,11 @@ module.exports = class bitvavo extends Exchange { // feeCurrency: 'EUR' // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'side'); const id = this.safeString2 (trade, 'id', 'fillId'); @@ -34469,7 +34348,7 @@ module.exports = class bitvavo extends Exchange { if (taker !== undefined) { takerOrMaker = taker ? 'taker' : 'maker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); @@ -34540,11 +34419,11 @@ module.exports = class bitvavo extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -34592,13 +34471,12 @@ module.exports = class bitvavo extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'inOrder'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'inOrder'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDepositAddress (code, params = {}) { @@ -34648,7 +34526,7 @@ module.exports = class bitvavo extends Exchange { if (price !== undefined) { cost = amount * price; } else { - cost = this.safeFloat2 (params, 'cost', 'amountQuote'); + cost = this.safeNumber2 (params, 'cost', 'amountQuote'); } if (cost !== undefined) { const precision = market['precision']['price']; @@ -34661,7 +34539,7 @@ module.exports = class bitvavo extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['amount'] = this.amountToPrecision (symbol, amount); } else if (isStopMarket || isStopLimit) { - let stopPrice = this.safeFloat2 (params, 'stopPrice', 'triggerAmount'); + let stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerAmount'); if (stopPrice === undefined) { if (isStopLimit) { throw new ArgumentsRequired (this.id + ' createOrder requires a stopPrice parameter for a ' + type + ' order'); @@ -34723,7 +34601,7 @@ module.exports = class bitvavo extends Exchange { await this.loadMarkets (); const market = this.market (symbol); let request = {}; - const amountRemaining = this.safeFloat (params, 'amountRemaining'); + const amountRemaining = this.safeNumber (params, 'amountRemaining'); params = this.omit (params, 'amountRemaining'); if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); @@ -34788,7 +34666,6 @@ module.exports = class bitvavo extends Exchange { throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument'); } await this.loadMarkets (); - await this.loadMarkets (); const market = this.market (symbol); const request = { 'orderId': id, @@ -35014,26 +34891,13 @@ module.exports = class bitvavo extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let remaining = this.safeFloat (order, 'amountRemaining'); - let filled = this.safeFloat (order, 'filledAmount'); - const remainingCost = this.safeFloat (order, 'remainingCost'); - if ((remainingCost !== undefined) && (remainingCost === 0.0)) { - remaining = 0; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - const cost = this.safeFloat (order, 'filledAmountQuote'); - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amountRemaining'); + const filled = this.safeNumber (order, 'filledAmount'); + const cost = this.safeNumber (order, 'filledAmountQuote'); let fee = undefined; - const feeCost = this.safeFloat (order, 'feePaid'); + const feeCost = this.safeNumber (order, 'feePaid'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -35042,32 +34906,24 @@ module.exports = class bitvavo extends Exchange { 'currency': feeCurrencyCode, }; } - let lastTradeTimestamp = undefined; - const rawTrades = this.safeValue (order, 'fills'); - let trades = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'symbol': symbol, - 'order': id, - 'side': side, - }); - const numTrades = trades.length; - if (numTrades > 0) { - const lastTrade = this.safeValue (trades, numTrades - 1); - lastTradeTimestamp = lastTrade['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'symbol': symbol, + 'order': id, + 'side': side, + 'type': type, + }); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = this.safeValue (order, 'postOnly'); // https://github.com/ccxt/ccxt/issues/8489 - const stopPrice = this.safeFloat (order, 'triggerPrice'); - return { + const stopPrice = this.safeNumber (order, 'triggerPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -35077,13 +34933,13 @@ module.exports = class bitvavo extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -35278,11 +35134,11 @@ module.exports = class bitvavo extends Exchange { const currencyId = this.safeString (transaction, 'symbol'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -35373,7 +35229,7 @@ module.exports = class bitvavo extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],45:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],45:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -35435,7 +35291,7 @@ module.exports = class bitz extends Exchange { 'assets': 'https://{hostname}', }, 'www': 'https://www.bitz.com', - 'doc': 'https://apidoc.bitz.com/en/', + 'doc': 'https://apidocv2.bitz.plus/en/', 'fees': 'https://www.bitz.com/fee?type=1', 'referral': 'https://u.bitz.com/register?invite_code=1429193', }, @@ -35452,6 +35308,11 @@ module.exports = class bitz extends Exchange { 'currencyRate', 'currencyCoinRate', 'coinRate', + 'getContractCoin', + 'getContractKline', + 'getContractOrderBook', + 'getContractTradesHistory', + 'getContractTickers', ], }, 'trade': { @@ -35464,6 +35325,10 @@ module.exports = class bitz extends Exchange { 'getUserNowEntrustSheet', // open orders 'getEntrustSheetInfo', // order 'depositOrWithdraw', // transactions + 'getCoinAddress', + 'getCoinAddressList', + 'marketTrade', + 'addEntrustSheetBatch', ], }, 'assets': { @@ -35471,6 +35336,20 @@ module.exports = class bitz extends Exchange { 'getUserAssets', ], }, + 'contract': { + 'post': [ + 'addContractTrade', + 'cancelContractTrade', + 'getContractActivePositions', + 'getContractAccountInfo', + 'getContractMyPositions', + 'getContractOrderResult', + 'getContractTradeResult', + 'getContractOrder', + 'getContractMyHistoryTrade', + 'getContractMyTrades', + ], + }, }, 'fees': { 'trading': { @@ -35657,8 +35536,8 @@ module.exports = class bitz extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTrade'), - 'max': this.safeFloat (market, 'maxTrade'), + 'min': this.safeNumber (market, 'minTrade'), + 'max': this.safeNumber (market, 'maxTrade'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -35707,12 +35586,12 @@ module.exports = class bitz extends Exchange { const currencyId = this.safeString (balance, 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lock'); - account['total'] = this.safeFloat (balance, 'num'); - account['free'] = this.safeFloat (balance, 'over'); + account['used'] = this.safeString (balance, 'lock'); + account['total'] = this.safeString (balance, 'num'); + account['free'] = this.safeString (balance, 'over'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTicker (ticker, market = undefined) { @@ -35742,8 +35621,8 @@ module.exports = class bitz extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'now'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'now'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -35754,22 +35633,22 @@ module.exports = class bitz extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': change, - 'percentage': this.safeFloat (ticker, 'priceChange24h'), + 'percentage': this.safeNumber (ticker, 'priceChange24h'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -35959,8 +35838,8 @@ module.exports = class bitz extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'p'); - const amount = this.safeFloat (trade, 'n'); + const price = this.safeNumber (trade, 'p'); + const amount = this.safeNumber (trade, 'n'); let cost = undefined; if (price !== undefined) { if (amount !== undefined) { @@ -36028,11 +35907,11 @@ module.exports = class bitz extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -36130,22 +36009,17 @@ module.exports = class bitz extends Exchange { if (side !== undefined) { side = (side === 'sale') ? 'sell' : 'buy'; } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'number'); - const remaining = this.safeFloat (order, 'numberOver'); - const filled = this.safeFloat (order, 'numberDeal'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'number'); + const remaining = this.safeNumber (order, 'numberOver'); + const filled = this.safeNumber (order, 'numberDeal'); let timestamp = this.safeInteger (order, 'timestamp'); if (timestamp === undefined) { timestamp = this.safeTimestamp (order, 'created'); } - let cost = this.safeFloat (order, 'orderTotalPrice'); - if (price !== undefined) { - if (filled !== undefined) { - cost = filled * price; - } - } + const cost = this.safeNumber (order, 'orderTotalPrice'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -36167,7 +36041,7 @@ module.exports = class bitz extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -36494,7 +36368,7 @@ module.exports = class bitz extends Exchange { const type = this.safeStringLower (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'network_fee'); + const feeCost = this.safeNumber (transaction, 'network_fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -36509,7 +36383,7 @@ module.exports = class bitz extends Exchange { 'address': this.safeString (transaction, 'wallet'), 'tag': this.safeString (transaction, 'memo'), 'type': type, - 'amount': this.safeFloat (transaction, 'number'), + 'amount': this.safeNumber (transaction, 'number'), 'currency': code, 'status': status, 'updated': timestamp, @@ -36661,12 +36535,13 @@ module.exports = class bitz extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],46:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],46:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -36745,17 +36620,19 @@ module.exports = class bl3p extends Exchange { const available = this.safeValue (wallet, 'available', {}); const balance = this.safeValue (wallet, 'balance', {}); const account = this.account (); - account['free'] = this.safeFloat (available, 'value'); - account['total'] = this.safeFloat (balance, 'value'); + account['free'] = this.safeString (available, 'value'); + account['total'] = this.safeString (balance, 'value'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { + const price = this.safeNumber (bidask, priceKey); + const size = this.safeNumber (bidask, amountKey); return [ - bidask[priceKey] / 100000.0, - bidask[amountKey] / 100000000.0, + price / 100000.0, + size / 100000000.0, ]; } @@ -36775,16 +36652,16 @@ module.exports = class bl3p extends Exchange { }; const ticker = await this.publicGetMarketTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -36794,7 +36671,7 @@ module.exports = class bl3p extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker['volume'], '24h'), + 'baseVolume': this.safeNumber (ticker['volume'], '24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -36803,20 +36680,13 @@ module.exports = class bl3p extends Exchange { parseTrade (trade, market = undefined) { const id = this.safeString (trade, 'trade_id'); const timestamp = this.safeInteger (trade, 'date'); - let price = this.safeFloat (trade, 'price_int'); - if (price !== undefined) { - price /= 100000.0; - } - let amount = this.safeFloat (trade, 'amount_int'); - if (amount !== undefined) { - amount /= 100000000.0; - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + let priceString = this.safeString (trade, 'price_int'); + priceString = Precise.stringDiv (priceString, '100000'); + let amountString = this.safeString (trade, 'amount_int'); + amountString = Precise.stringDiv (amountString, '100000000'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -36899,7 +36769,7 @@ module.exports = class bl3p extends Exchange { } }; -},{"./base/Exchange":6}],47:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],47:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -37065,8 +36935,8 @@ module.exports = class bleutrade extends Exchange { 'code': code, 'name': this.safeString (item, 'AssetLong'), 'active': this.safeValue (item, 'IsActive') && !this.safeValue (item, 'MaintenanceMode'), - 'fee': this.safeFloat (item, 'WithdrawTxFee'), - 'precision': this.safeFloat (item, 'DecimalPlaces'), + 'fee': this.safeNumber (item, 'WithdrawTxFee'), + 'precision': this.safeNumber (item, 'DecimalPlaces'), 'info': item, 'limits': this.limits, }; @@ -37118,7 +36988,7 @@ module.exports = class bleutrade extends Exchange { 'taker': this.fees['trading']['taker'], 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinTradeSize'), + 'min': this.safeNumber (market, 'MinTradeSize'), 'max': undefined, }, 'price': { @@ -37194,8 +37064,8 @@ module.exports = class bleutrade extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'TimeStamp')); const marketId = this.safeString (ticker, 'MarketName'); const symbol = this.safeSymbol (marketId, market, '_'); - const previous = this.safeFloat (ticker, 'PrevDay'); - const last = this.safeFloat (ticker, 'Last'); + const previous = this.safeNumber (ticker, 'PrevDay'); + const last = this.safeNumber (ticker, 'Last'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -37210,11 +37080,11 @@ module.exports = class bleutrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'High'), - 'low': this.safeFloat (ticker, 'Low'), - 'bid': this.safeFloat (ticker, 'Bid'), + 'high': this.safeNumber (ticker, 'High'), + 'low': this.safeNumber (ticker, 'Low'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': previous, @@ -37224,8 +37094,8 @@ module.exports = class bleutrade extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume'), - 'quoteVolume': this.safeFloat (ticker, 'BaseVolume'), + 'baseVolume': this.safeNumber (ticker, 'Volume'), + 'quoteVolume': this.safeNumber (ticker, 'BaseVolume'), 'info': ticker, }; } @@ -37233,11 +37103,11 @@ module.exports = class bleutrade extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (ohlcv['TimeStamp'] + '+00:00'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -37313,11 +37183,11 @@ module.exports = class bleutrade extends Exchange { const currencyId = this.safeString (item, 'Asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (item, 'Available'); - account['total'] = this.safeFloat (item, 'Balance'); + account['free'] = this.safeString (item, 'Available'); + account['total'] = this.safeString (item, 'Balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -37460,7 +37330,7 @@ module.exports = class bleutrade extends Exchange { // } const timestamp = this.parse8601 (this.safeString (item, 'TimeStamp')); - let amount = this.safeFloat (item, 'Amount'); + let amount = this.safeNumber (item, 'Amount'); let direction = undefined; if (amount !== undefined) { direction = 'in'; @@ -37534,27 +37404,12 @@ module.exports = class bleutrade extends Exchange { if ('Created' in order) { timestamp = this.parse8601 (order['Created'] + '+00:00'); } - let price = this.safeFloat (order, 'Price'); - let cost = undefined; - const amount = this.safeFloat (order, 'Quantity'); - const remaining = this.safeFloat (order, 'QuantityRemaining'); - let filled = undefined; - if (amount !== undefined && remaining !== undefined) { - filled = amount - remaining; - } - if (!cost) { - if (price && filled) { - cost = price * filled; - } - } - if (!price) { - if (cost && filled) { - price = cost / filled; - } - } - const average = this.safeFloat (order, 'PricePerUnit'); + const price = this.safeNumber (order, 'Price'); + const amount = this.safeNumber (order, 'Quantity'); + const remaining = this.safeNumber (order, 'QuantityRemaining'); + const average = this.safeNumber (order, 'PricePerUnit'); const id = this.safeString (order, 'OrderID'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -37568,15 +37423,15 @@ module.exports = class bleutrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -37613,7 +37468,7 @@ module.exports = class bleutrade extends Exchange { // Symbol: 'BTC' } // const id = this.safeString (transaction, 'ID'); - let amount = this.safeFloat (transaction, 'Amount'); + let amount = this.safeNumber (transaction, 'Amount'); let type = 'deposit'; if (amount < 0) { amount = Math.abs (amount); @@ -37715,13 +37570,14 @@ module.exports = class bleutrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],48:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],48:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -37902,11 +37758,11 @@ module.exports = class braziliex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': this.safeFloat (currency, 'txWithdrawalFee'), + 'fee': this.safeNumber (currency, 'txWithdrawalFee'), }, 'deposit': { 'active': canDeposit, - 'fee': this.safeFloat (currency, 'txDepositFee'), + 'fee': this.safeNumber (currency, 'txDepositFee'), }, }, 'limits': { @@ -37923,11 +37779,11 @@ module.exports = class braziliex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'MinWithdrawal'), + 'min': this.safeNumber (currency, 'MinWithdrawal'), 'max': Math.pow (10, precision), }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, }, @@ -37975,9 +37831,9 @@ module.exports = class braziliex extends Exchange { const quoteIsFiat = this.safeInteger (quoteCurrency, 'is_fiat', 0); let minCost = undefined; if (quoteIsFiat) { - minCost = this.safeFloat (baseCurrency, 'minAmountTradeFIAT'); + minCost = this.safeNumber (baseCurrency, 'minAmountTradeFIAT'); } else { - minCost = this.safeFloat (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); + minCost = this.safeNumber (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); } const isActive = this.safeInteger (market, 'active'); const active = (isActive === 1); @@ -38020,27 +37876,27 @@ module.exports = class braziliex extends Exchange { symbol = market['symbol']; } const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highestBid24'), - 'low': this.safeFloat (ticker, 'lowestAsk24'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'highestBid24'), + 'low': this.safeNumber (ticker, 'lowestAsk24'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'percentChange'), + 'change': this.safeNumber (ticker, 'percentChange'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume24'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume24'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24'), 'info': ticker, }; } @@ -38080,13 +37936,18 @@ module.exports = class braziliex extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString2 (trade, 'date_exec', 'date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } - const cost = this.safeFloat (trade, 'total'); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_number'); const type = 'limit'; const side = this.safeString (trade, 'type'); @@ -38128,11 +37989,11 @@ module.exports = class braziliex extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -38154,21 +38015,16 @@ module.exports = class braziliex extends Exchange { if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'date')); } - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'total', 0.0); - const amount = this.safeFloat (order, 'amount'); - const filledPercentage = this.safeFloat (order, 'progress'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'total'); + const amount = this.safeNumber (order, 'amount'); + const filledPercentage = this.safeNumber (order, 'progress'); const filled = amount * filledPercentage; - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); - let info = order; - if ('info' in info) { - info = order['info']; - } const id = this.safeString (order, 'order_number'); const fee = this.safeValue (order, 'fee'); // propagated from createOrder const status = (filledPercentage === 1.0) ? 'closed' : 'open'; const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -38185,12 +38041,12 @@ module.exports = class braziliex extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, - 'info': info, + 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -38242,7 +38098,7 @@ module.exports = class braziliex extends Exchange { 'price': this.safeString (priceParts, 1), 'total': this.safeString (totalParts, 1), 'fee': { - 'cost': this.safeFloat (feeParts, 1), + 'cost': this.safeNumber (feeParts, 1), 'currency': this.safeString (feeParts, 2), }, 'progress': '0.0', @@ -38359,13 +38215,14 @@ module.exports = class braziliex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],49:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],49:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, DDoSProtection, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -38507,8 +38364,8 @@ module.exports = class btcalpha extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -38560,14 +38417,11 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'id', 'tid'); const side = this.safeString2 (trade, 'my_side', 'side'); const orderId = this.safeString (trade, 'o_id'); @@ -38616,11 +38470,11 @@ module.exports = class btcalpha extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -38657,11 +38511,11 @@ module.exports = class btcalpha extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'reserve'); - account['total'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserve'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -38682,8 +38536,8 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (order, 'date'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString2 (order, 'oid', 'id'); let trades = this.safeValue (order, 'trades', []); @@ -38864,13 +38718,14 @@ module.exports = class btcalpha extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],50:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],50:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -38955,12 +38810,12 @@ module.exports = class btcbox extends Exchange { if (free in response) { const account = this.account (); const used = currencyId + '_lock'; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -38981,16 +38836,16 @@ module.exports = class btcbox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -39000,8 +38855,8 @@ module.exports = class btcbox extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -39025,14 +38880,11 @@ module.exports = class btcbox extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeString (trade, 'type'); return { @@ -39132,15 +38984,15 @@ module.exports = class btcbox extends Exchange { if (datetimeString !== undefined) { timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time } - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let cost = undefined; if (price !== undefined) { if (filled !== undefined) { @@ -39292,7 +39144,7 @@ module.exports = class btcbox extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],51:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],51:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -39541,11 +39393,11 @@ module.exports = class btcmarkets extends Exchange { const tagTo = tag; const addressFrom = undefined; const tagFrom = undefined; - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const currencyId = this.safeString (transaction, 'assetName'); const code = this.safeCurrencyCode (currencyId); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (fee) { amount -= fee; } @@ -39598,10 +39450,10 @@ module.exports = class btcmarkets extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const fees = this.safeValue (this.safeValue (this.options, 'fees', {}), quote, this.fees); - const pricePrecision = this.safeFloat (market, 'priceDecimals'); - const amountPrecision = this.safeFloat (market, 'amountDecimals'); - const minAmount = this.safeFloat (market, 'minOrderAmount'); - const maxAmount = this.safeFloat (market, 'maxOrderAmount'); + const pricePrecision = this.safeNumber (market, 'priceDecimals'); + const amountPrecision = this.safeNumber (market, 'amountDecimals'); + const minAmount = this.safeNumber (market, 'minOrderAmount'); + const maxAmount = this.safeNumber (market, 'maxOrderAmount'); let minPrice = undefined; if (quote === 'AUD') { minPrice = Math.pow (10, -pricePrecision); @@ -39660,14 +39512,12 @@ module.exports = class btcmarkets extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetName'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance, 'balance'); - const used = this.safeFloat (balance, 'locked'); const account = this.account (); - account['used'] = used; - account['total'] = total; + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -39683,11 +39533,11 @@ module.exports = class btcmarkets extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 0)), - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 2), // high - this.safeFloat (ohlcv, 3), // low - this.safeFloat (ohlcv, 4), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 2), // high + this.safeNumber (ohlcv, 3), // low + this.safeNumber (ohlcv, 4), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -39783,21 +39633,21 @@ module.exports = class btcmarkets extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'lastPrice'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); - const quoteVolume = this.safeFloat (ticker, 'volumeQte24h'); + const last = this.safeNumber (ticker, 'lastPrice'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); + const quoteVolume = this.safeNumber (ticker, 'volumeQte24h'); const vwap = this.vwap (baseVolume, quoteVolume); - const change = this.safeFloat (ticker, 'price24h'); - const percentage = this.safeFloat (ticker, 'pricePct24h'); + const change = this.safeNumber (ticker, 'price24h'); + const percentage = this.safeNumber (ticker, 'pricePct24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bestBid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'bestAsk'), + 'ask': this.safeNumber (ticker, 'bestAsk'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -39908,8 +39758,8 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -39918,7 +39768,7 @@ module.exports = class btcmarkets extends Exchange { } const orderId = this.safeString (trade, 'orderId'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -40009,7 +39859,7 @@ module.exports = class btcmarkets extends Exchange { } } if (triggerPriceIsRequired) { - const triggerPrice = this.safeFloat (params, 'triggerPrice'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); params = this.omit (params, 'triggerPrice'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a triggerPrice parameter for a ' + type + 'order'); @@ -40142,9 +39992,9 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const type = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'openAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'openAmount'); let filled = undefined; if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); @@ -40159,7 +40009,7 @@ module.exports = class btcmarkets extends Exchange { const id = this.safeString (order, 'orderId'); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -40351,13 +40201,14 @@ module.exports = class btcmarkets extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],52:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],52:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -40460,10 +40311,10 @@ module.exports = class btctradeua extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -40603,14 +40454,11 @@ module.exports = class btctradeua extends Exchange { const id = this.safeString (trade, 'id'); const type = 'limit'; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amnt_trade'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amnt_trade'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -40691,11 +40539,11 @@ module.exports = class btctradeua extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'amnt_trade'), + 'amount': this.safeNumber (order, 'amnt_trade'), 'filled': 0, - 'remaining': this.safeFloat (order, 'amnt_trade'), + 'remaining': this.safeNumber (order, 'amnt_trade'), 'trades': undefined, 'info': order, 'cost': undefined, @@ -40747,7 +40595,7 @@ module.exports = class btctradeua extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],53:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],53:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -40875,13 +40723,13 @@ module.exports = class btcturk extends Exchange { const used = currency['id'] + '_reserved'; if (free in response) { const account = this.account (); - account['free'] = this.safeFloat (response, free); - account['total'] = this.safeFloat (response, total); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['total'] = this.safeString (response, total); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -40901,26 +40749,26 @@ module.exports = class btcturk extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'average'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -40954,8 +40802,8 @@ module.exports = class btcturk extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -40997,11 +40845,11 @@ module.exports = class btcturk extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (this.safeString (ohlcv, 'Time')), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -41076,13 +40924,14 @@ module.exports = class btcturk extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],54:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],54:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -41299,7 +41148,7 @@ module.exports = class buda extends Exchange { } const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); - const precision = this.safeFloat (currency, 'input_decimals'); + const precision = this.safeNumber (currency, 'input_decimals'); const minimum = Math.pow (10, -precision); result[code] = { 'id': id, @@ -41460,24 +41309,25 @@ module.exports = class buda extends Exchange { let timestamp = undefined; let side = undefined; const type = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; const order = undefined; const fee = undefined; let symbol = undefined; - let cost = undefined; if (market) { symbol = market['symbol']; } if (Array.isArray (trade)) { - timestamp = parseInt (trade[0]); - price = parseFloat (trade[1]); - amount = parseFloat (trade[2]); - cost = price * amount; - side = trade[3]; - id = trade[4].toString (); + timestamp = this.safeInteger (trade, 0); + priceString = this.safeString (trade, 1); + amountString = this.safeString (trade, 2); + side = this.safeString (trade, 3); + id = this.safeString (trade, 4); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': order, @@ -41532,11 +41382,11 @@ module.exports = class buda extends Exchange { const currencyId = this.safeString (balance, 'id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = parseFloat (balance['available_amount'][0]); - account['total'] = parseFloat (balance['amount'][0]); + account['free'] = this.safeString (balance['available_amount'], 0); + account['total'] = this.safeString (balance['amount'], 0); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -41644,15 +41494,15 @@ module.exports = class buda extends Exchange { const side = this.safeStringLower (order, 'type'); const status = this.parseOrderStatus (this.safeString (order, 'state')); const originalAmount = this.safeValue (order, 'original_amount', []); - const amount = this.safeFloat (originalAmount, 0); + const amount = this.safeNumber (originalAmount, 0); const remainingAmount = this.safeValue (order, 'amount', []); - const remaining = this.safeFloat (remainingAmount, 0); + const remaining = this.safeNumber (remainingAmount, 0); const tradedAmount = this.safeValue (order, 'traded_amount', []); - const filled = this.safeFloat (tradedAmount, 0); + const filled = this.safeNumber (tradedAmount, 0); const totalExchanged = this.safeValue (order, 'totalExchanged', []); - const cost = this.safeFloat (totalExchanged, 0); + const cost = this.safeNumber (totalExchanged, 0); const limitPrice = this.safeValue (order, 'limit', []); - let price = this.safeFloat (limitPrice, 0); + let price = this.safeNumber (limitPrice, 0); if (price === undefined) { if (limitPrice !== undefined) { price = limitPrice; @@ -41663,7 +41513,7 @@ module.exports = class buda extends Exchange { average = this.priceToPrecision (symbol, cost / filled); } const paidFee = this.safeValue (order, 'paid_fee', []); - const feeCost = this.safeFloat (paidFee, 0); + const feeCost = this.safeNumber (paidFee, 0); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (paidFee, 1); @@ -41902,13 +41752,14 @@ module.exports = class buda extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],55:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],55:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { RateLimitExceeded, BadSymbol, OrderNotFound, ExchangeError, AuthenticationError, ArgumentsRequired, ExchangeNotAvailable } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -42090,7 +41941,7 @@ module.exports = class bw extends Exchange { const symbol = base + '/' + quote; const state = this.safeInteger (market, 'state'); const active = (state === 1); - const fee = this.safeFloat (market, 'defaultFee'); + const fee = this.safeNumber (market, 'defaultFee'); result.push ({ 'id': id, 'active': active, @@ -42111,7 +41962,7 @@ module.exports = class bw extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -42197,11 +42048,11 @@ module.exports = class bw extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'drawFee'), + 'fee': this.safeNumber (currency, 'drawFee'), 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'limitAmount', 0), + 'min': this.safeNumber (currency, 'limitAmount', 0), 'max': undefined, }, 'price': { @@ -42214,7 +42065,7 @@ module.exports = class bw extends Exchange { }, 'withdraw': { 'min': undefined, - 'max': this.safeFloat (currency, 'onceDrawLimit'), + 'max': this.safeNumber (currency, 'onceDrawLimit'), }, }, }; @@ -42251,9 +42102,9 @@ module.exports = class bw extends Exchange { 'high': parseFloat (this.safeValue (ticker, 2)), 'low': parseFloat (this.safeValue (ticker, 3)), 'bid': parseFloat (this.safeValue (ticker, 7)), - 'bidVolume': this.safeFloat (bid, 'quantity'), + 'bidVolume': this.safeNumber (bid, 'quantity'), 'ask': parseFloat (this.safeValue (ticker, 8)), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, 'open': undefined, 'close': close, @@ -42382,8 +42233,11 @@ module.exports = class bw extends Exchange { // ... // const timestamp = this.safeTimestamp (trade, 2); - const price = this.safeFloat (trade, 5); - const amount = this.safeFloat (trade, 6); + const priceString = this.safeString (trade, 5); + const amountString = this.safeString (trade, 6); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 1); let symbol = undefined; if (marketId !== undefined) { @@ -42400,12 +42254,6 @@ module.exports = class bw extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const sideString = this.safeString (trade, 4); const side = (sideString === 'ask') ? 'sell' : 'buy'; return { @@ -42419,7 +42267,7 @@ module.exports = class bw extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': parseFloat (cost), + 'cost': cost, 'fee': undefined, 'info': trade, }; @@ -42476,11 +42324,11 @@ module.exports = class bw extends Exchange { // return [ this.safeTimestamp (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - this.safeFloat (ohlcv, 6), - this.safeFloat (ohlcv, 7), - this.safeFloat (ohlcv, 8), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + this.safeNumber (ohlcv, 6), + this.safeNumber (ohlcv, 7), + this.safeNumber (ohlcv, 8), ]; } @@ -42538,11 +42386,11 @@ module.exports = class bw extends Exchange { const currencyId = this.safeString (balance, 'currencyTypeId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'amount'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'amount'); + account['used'] = this.safeString (balance, 'freeze'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -42638,25 +42486,13 @@ module.exports = class bw extends Exchange { } else if (side === '1') { side = 'buy'; } - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'completeAmount'); - let remaining = this.safeFloat2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available - let cost = this.safeFloat (order, 'totalMoney'); - if (filled !== undefined) { - if (amount !== undefined) { - if (remaining === undefined) { - remaining = amount - filled; - } - } - if (cost === undefined) { - if (price !== undefined) { - cost = filled * cost; - } - } - } + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'completeAmount'); + const remaining = this.safeNumber2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available + const cost = this.safeNumber (order, 'totalMoney'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'entrustId'), 'clientOrderId': undefined, @@ -42678,7 +42514,7 @@ module.exports = class bw extends Exchange { 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -42974,12 +42810,12 @@ module.exports = class bw extends Exchange { code = currency['code']; } const type = ('depositId' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat2 (transaction, 'actuallyAmount', 'amount'); + const amount = this.safeNumber2 (transaction, 'actuallyAmount', 'amount'); const status = this.parseTransactionStatus (this.safeString2 (transaction, 'verifyStatus', 'state')); const timestamp = this.safeInteger (transaction, 'createTime'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -43110,7 +42946,7 @@ module.exports = class bw extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],56:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],56:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -43155,6 +42991,7 @@ module.exports = class bybit extends Exchange { 'fetchTrades': true, 'fetchTransactions': false, 'fetchWithdrawals': true, + 'fetchPositions': true, }, 'timeframes': { '1m': '1', @@ -43186,6 +43023,34 @@ module.exports = class bybit extends Exchange { 'referral': 'https://www.bybit.com/app/register?ref=X7Prm', }, 'api': { + 'futures': { + 'private': { + 'get': [ + 'position/list', + 'order/list', + 'order', + 'stop-order/list', + 'stop-order', + 'execution/list', + 'trade/closed-pnl/list', + ], + 'post': [ + 'order/create', + 'order/cancel', + 'order/cancelAll', + 'order/replace', + 'stop-order/create', + 'stop-order/cancel', + 'stop-order/cancelAll', + 'stop-order/replace', + 'position/change-position-margin', + 'position/trading-stop', + 'position/leverage/save', + 'position/switch-mode', + 'position/switch-isolated', + ], + }, + }, 'v2': { 'public': { 'get': [ @@ -43399,7 +43264,11 @@ module.exports = class bybit extends Exchange { 'LTC/USDT': 'linear', 'XTZ/USDT': 'linear', 'LINK/USDT': 'linear', + 'ADA/USDT': 'linear', + 'DOT/USDT': 'linear', + 'UNI/USDT': 'linear', }, + 'defaultType': 'linear', // may also be inverse or inverseFuture 'code': 'BTC', 'cancelAllOrders': { // 'method': 'v2PrivatePostOrderCancelAll', // v2PrivatePostStopOrderCancelAll @@ -43514,8 +43383,8 @@ module.exports = class bybit extends Exchange { const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {}); const priceFilter = this.safeValue (market, 'price_filter', {}); const precision = { - 'amount': this.safeFloat (lotSizeFilter, 'qty_step'), - 'price': this.safeFloat (priceFilter, 'tick_size'), + 'amount': this.safeNumber (lotSizeFilter, 'qty_step'), + 'price': this.safeNumber (priceFilter, 'tick_size'), }; const status = this.safeString (market, 'status'); let active = undefined; @@ -43529,8 +43398,8 @@ module.exports = class bybit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'type': 'future', 'spot': false, 'future': true, @@ -43539,12 +43408,12 @@ module.exports = class bybit extends Exchange { 'inverse': inverse, 'limits': { 'amount': { - 'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'), - 'max': this.safeFloat (lotSizeFilter, 'max_trading_qty'), + 'min': this.safeNumber (lotSizeFilter, 'min_trading_qty'), + 'max': this.safeNumber (lotSizeFilter, 'max_trading_qty'), }, 'price': { - 'min': this.safeFloat (priceFilter, 'min_price'), - 'max': this.safeFloat (priceFilter, 'max_price'), + 'min': this.safeNumber (priceFilter, 'min_price'), + 'max': this.safeNumber (priceFilter, 'max_price'), }, 'cost': { 'min': undefined, @@ -43590,9 +43459,9 @@ module.exports = class bybit extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const open = this.safeFloat (ticker, 'prev_price_24h'); - let percentage = this.safeFloat (ticker, 'price_24h_pcnt'); + const last = this.safeNumber (ticker, 'last_price'); + const open = this.safeNumber (ticker, 'prev_price_24h'); + let percentage = this.safeNumber (ticker, 'price_24h_pcnt'); if (percentage !== undefined) { percentage *= 100; } @@ -43602,18 +43471,18 @@ module.exports = class bybit extends Exchange { change = last - open; average = this.sum (open, last) / 2; } - const baseVolume = this.safeFloat (ticker, 'turnover_24h'); - const quoteVolume = this.safeFloat (ticker, 'volume_24h'); + const baseVolume = this.safeNumber (ticker, 'turnover_24h'); + const quoteVolume = this.safeNumber (ticker, 'volume_24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price_24h'), - 'low': this.safeFloat (ticker, 'low_price_24h'), - 'bid': this.safeFloat (ticker, 'bid_price'), + 'high': this.safeNumber (ticker, 'high_price_24h'), + 'low': this.safeNumber (ticker, 'low_price_24h'), + 'bid': this.safeNumber (ticker, 'bid_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask_price'), + 'ask': this.safeNumber (ticker, 'ask_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -43762,11 +43631,11 @@ module.exports = class bybit extends Exchange { // return [ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat2 (ohlcv, 'turnover', 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber2 (ohlcv, 'turnover', 'volume'), ]; } @@ -43892,9 +43761,9 @@ module.exports = class bybit extends Exchange { const marketId = this.safeString (trade, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat2 (trade, 'qty', 'exec_qty'); - let cost = this.safeFloat (trade, 'exec_value'); - const price = this.safeFloat2 (trade, 'exec_price', 'price'); + const amount = this.safeNumber2 (trade, 'qty', 'exec_qty'); + let cost = this.safeNumber (trade, 'exec_value'); + const price = this.safeNumber2 (trade, 'exec_price', 'price'); if (cost === undefined) { if (amount !== undefined) { if (price !== undefined) { @@ -43909,14 +43778,14 @@ module.exports = class bybit extends Exchange { const side = this.safeStringLower (trade, 'side'); const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind'); const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker'; - const feeCost = this.safeFloat (trade, 'exec_fee'); + const feeCost = this.safeNumber (trade, 'exec_fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyCode = market['inverse'] ? market['base'] : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'fee_rate'), + 'rate': this.safeNumber (trade, 'fee_rate'), }; } return { @@ -44076,12 +43945,12 @@ module.exports = class bybit extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['used'] = this.safeFloat (balance, 'used_margin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'used_margin'); + account['total'] = this.safeString (balance, 'equity'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -44208,56 +44077,42 @@ module.exports = class bybit extends Exchange { // const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); - let symbol = undefined; - let base = undefined; + const symbol = market['symbol']; + let feeCurrency = undefined; const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const id = this.safeString2 (order, 'order_id', 'stop_order_id'); const type = this.safeStringLower (order, 'order_type'); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - let average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'qty'); - let cost = this.safeFloat (order, 'cum_exec_value'); - let filled = this.safeFloat (order, 'cum_exec_qty'); - let remaining = this.safeFloat (order, 'leaves_qty'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'qty'); + const cost = this.safeNumber (order, 'cum_exec_value'); + const filled = this.safeNumber (order, 'cum_exec_qty'); + const remaining = this.safeNumber (order, 'leaves_qty'); + const marketTypes = this.safeValue (this.options, 'marketTypes', {}); + const marketType = this.safeString (marketTypes, symbol); if (market !== undefined) { - symbol = market['symbol']; - base = market['base']; + if (marketType === 'linear') { + feeCurrency = market['quote']; + } else { + feeCurrency = market['base']; + } } let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time'); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = amount - remaining; - } - if (filled !== undefined) { - if ((remaining === undefined) && (amount !== undefined)) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if ((type === 'market') && (cost !== undefined) && (cost > 0)) { - price = undefined; - if (average === undefined) { - average = filled / cost; - } - } - } const status = this.parseOrderStatus (this.safeString2 (order, 'order_status', 'stop_order_status')); const side = this.safeStringLower (order, 'side'); - let feeCost = this.safeFloat (order, 'cum_exec_fee'); + let feeCost = this.safeNumber (order, 'cum_exec_fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); fee = { 'cost': feeCost, - 'currency': base, + 'currency': feeCurrency, }; } let clientOrderId = this.safeString (order, 'order_link_id'); @@ -44265,9 +44120,9 @@ module.exports = class bybit extends Exchange { clientOrderId = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'stop_px'); + const stopPrice = this.safeNumber (order, 'stop_px'); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -44289,7 +44144,7 @@ module.exports = class bybit extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -45140,7 +44995,8 @@ module.exports = class bybit extends Exchange { const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); + const type = this.safeStringLower (transaction, 'type'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -45160,8 +45016,8 @@ module.exports = class bybit extends Exchange { 'tag': undefined, 'tagTo': undefined, 'tagFrom': undefined, - 'type': 'withdrawal', - 'amount': this.safeFloat (transaction, 'amount'), + 'type': type, + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -45244,8 +45100,8 @@ module.exports = class bybit extends Exchange { // const currencyId = this.safeString (item, 'coin'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'wallet_balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'wallet_balance'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -45311,7 +45167,8 @@ module.exports = class bybit extends Exchange { 'recv_window': this.options['recvWindow'], 'timestamp': timestamp, }); - const auth = this.rawencode (this.keysort (query)); + const sortedQuery = this.keysort (query); + const auth = this.rawencode (sortedQuery); const signature = this.hmac (this.encode (auth), this.encode (this.secret)); if (method === 'POST') { body = this.json (this.extend (query, { @@ -45321,7 +45178,7 @@ module.exports = class bybit extends Exchange { 'Content-Type': 'application/json', }; } else { - request += '?' + auth + '&sign=' + signature; + request += '?' + this.urlencode (sortedQuery) + '&sign=' + signature; } } url += request; @@ -45344,17 +45201,48 @@ module.exports = class bybit extends Exchange { // time_now: '1583934106.590436' // } // - const errorCode = this.safeValue (response, 'ret_code'); - if (errorCode !== 0) { + const errorCode = this.safeString (response, 'ret_code'); + if (errorCode !== '0') { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback); this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback); throw new ExchangeError (feedback); // unknown message } } + + async fetchPositions (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (Array.isArray (symbols)) { + const length = symbols.length; + if (length !== 1) { + throw new ArgumentsRequired (this.id + ' fetchPositions takes exactly one symbol'); + } + request['symbol'] = this.marketId (symbols[0]); + } + const defaultType = this.safeString (this.options, 'defaultType', 'linear'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + let response = undefined; + if (type === 'linear') { + response = await this.privateLinearGetPositionList (this.extend (request, params)); + } else if (type === 'inverse') { + response = await this.v2PrivateGetPositionList (this.extend (request, params)); + } else if (type === 'inverseFuture') { + response = await this.futuresPrivateGetPositionList (this.extend (request, params)); + } + // { + // ret_code: 0, + // ret_msg: 'OK', + // ext_code: '', + // ext_info: '', + // result: [] or {} depending on the request + // } + return this.safeValue (response, 'result'); + } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],57:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],57:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -45543,12 +45431,12 @@ module.exports = class bytetrade extends Exchange { const limits = this.safeValue (currency, 'limits'); const deposit = this.safeValue (limits, 'deposit'); const amountPrecision = this.safeInteger (currency, 'basePrecision'); - let maxDeposit = this.safeFloat (deposit, 'max'); + let maxDeposit = this.safeNumber (deposit, 'max'); if (maxDeposit === -1.0) { maxDeposit = undefined; } const withdraw = this.safeValue (limits, 'withdraw'); - let maxWithdraw = this.safeFloat (withdraw, 'max'); + let maxWithdraw = this.safeNumber (withdraw, 'max'); if (maxWithdraw === -1.0) { maxWithdraw = undefined; } @@ -45564,11 +45452,11 @@ module.exports = class bytetrade extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (deposit, 'min'), + 'min': this.safeNumber (deposit, 'min'), 'max': maxDeposit, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'min'), + 'min': this.safeNumber (withdraw, 'min'), 'max': maxWithdraw, }, }, @@ -45622,12 +45510,12 @@ module.exports = class bytetrade extends Exchange { 'normalSymbol': normalSymbol, 'limits': { 'amount': { - 'min': this.safeFloat (amount, 'min'), - 'max': this.safeFloat (amount, 'max'), + 'min': this.safeNumber (amount, 'min'), + 'max': this.safeNumber (amount, 'max'), }, 'price': { - 'min': this.safeFloat (price, 'min'), - 'max': this.safeFloat (price, 'max'), + 'min': this.safeNumber (price, 'min'), + 'max': this.safeNumber (price, 'max'), }, 'cost': { 'min': undefined, @@ -45655,11 +45543,11 @@ module.exports = class bytetrade extends Exchange { const currencyId = this.safeString (balance, 'code'); const code = this.safeCurrencyCode (currencyId, undefined); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'used'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'used'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -45720,22 +45608,22 @@ module.exports = class bytetrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'open'), - 'close': this.safeFloat (ticker, 'close'), - 'last': this.safeFloat (ticker, 'last'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'open'), + 'close': this.safeNumber (ticker, 'close'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, // previous day close - 'change': this.safeFloat (ticker, 'change'), - 'percentage': this.safeFloat (ticker, 'percentage'), + 'change': this.safeNumber (ticker, 'change'), + 'percentage': this.safeNumber (ticker, 'percentage'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -45778,24 +45666,16 @@ module.exports = class bytetrade extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetDepth (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetDepth (params); + return this.parseTickers (response, symbols); } async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetTickers (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetTickers (params); + return this.parseTickers (response, symbols); } parseOHLCV (ohlcv, market = undefined) { @@ -45811,11 +45691,11 @@ module.exports = class bytetrade extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -45845,9 +45725,9 @@ module.exports = class bytetrade extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeInteger (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - const cost = this.safeFloat (trade, 'cost'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + const cost = this.safeNumber (trade, 'cost'); const id = this.safeString (trade, 'id'); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'takerOrMaker'); @@ -45917,12 +45797,12 @@ module.exports = class bytetrade extends Exchange { const timestamp = this.safeInteger (order, 'timestamp'); const datetime = this.safeString (order, 'datetime'); const lastTradeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled'); - const remaining = this.safeFloat (order, 'remaining'); - const cost = this.safeFloat (order, 'cost'); - const average = this.safeFloat (order, 'average'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled'); + const remaining = this.safeNumber (order, 'remaining'); + const cost = this.safeNumber (order, 'cost'); + const average = this.safeNumber (order, 'average'); const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); @@ -46315,7 +46195,7 @@ module.exports = class bytetrade extends Exchange { }; } - async transfer (code, amount, address, message = '', params = {}) { + async transfer (code, amount, fromAccount, toAccount, params = {}) { this.checkRequiredDependencies (); if (this.apiKey === undefined) { throw new ArgumentsRequired ('transfer() requires this.apiKey'); @@ -46333,6 +46213,7 @@ module.exports = class bytetrade extends Exchange { expirationDatetime = expirationDatetime.split ('.')[0]; const feeAmount = '300000000000000'; const defaultDappId = 'Sagittarius'; + const message = this.safeString (params, 'message', ''); const dappId = this.safeString (params, 'dappId', defaultDappId); const eightBytes = this.integerPow ('2', '64'); const byteStringArray = [ @@ -46346,8 +46227,8 @@ module.exports = class bytetrade extends Exchange { this.numberToLE (feeAmount, 8), // string for 32 bit php this.numberToLE (this.apiKey.length, 1), this.stringToBinary (this.encode (this.apiKey)), - this.numberToLE (address.length, 1), - this.stringToBinary (this.encode (address)), + this.numberToLE (toAccount.length, 1), + this.stringToBinary (this.encode (toAccount)), this.numberToLE (assetType, 4), this.numberToLE (this.integerDivide (amountChain, eightBytes), 8), this.numberToLE (this.integerModulo (amountChain, eightBytes), 8), @@ -46368,7 +46249,7 @@ module.exports = class bytetrade extends Exchange { const operation = { 'fee': '300000000000000', 'from': this.apiKey, - 'to': address, + 'to': toAccount, 'asset_type': parseInt (currency['id']), 'amount': amountChain.toString (), 'message': message, @@ -46522,9 +46403,9 @@ module.exports = class bytetrade extends Exchange { const datetime = this.safeString (transaction, 'datetime'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const feeInfo = this.safeValue (transaction, 'fee'); - const feeCost = this.safeFloat (feeInfo, 'cost'); + const feeCost = this.safeNumber (feeInfo, 'cost'); const feeCurrencyId = this.safeString (feeInfo, 'code'); const feeCode = this.safeCurrencyCode (feeCurrencyId, currency); const fee = { @@ -46787,7 +46668,7 @@ module.exports = class bytetrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],58:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],58:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -46822,7 +46703,7 @@ module.exports = class cdax extends huobipro { } }; -},{"./huobipro.js":96}],59:[function(require,module,exports){ +},{"./huobipro.js":94}],59:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -47081,7 +46962,7 @@ module.exports = class cex extends Exchange { 'fee': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimumCurrencyAmount'), + 'min': this.safeNumber (currency, 'minimumCurrencyAmount'), 'max': undefined, }, 'price': { @@ -47093,7 +46974,7 @@ module.exports = class cex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimalWithdrawalAmount'), + 'min': this.safeNumber (currency, 'minimalWithdrawalAmount'), 'max': undefined, }, }, @@ -47176,15 +47057,15 @@ module.exports = class cex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minLotSize'), - 'max': this.safeFloat (market, 'maxLotSize'), + 'min': this.safeNumber (market, 'minLotSize'), + 'max': this.safeNumber (market, 'maxLotSize'), }, 'price': { - 'min': this.safeFloat (market, 'minPrice'), - 'max': this.safeFloat (market, 'maxPrice'), + 'min': this.safeNumber (market, 'minPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { - 'min': this.safeFloat (market, 'minLotSizeS2'), + 'min': this.safeNumber (market, 'minLotSizeS2'), 'max': undefined, }, }, @@ -47205,13 +47086,13 @@ module.exports = class cex extends Exchange { const currencyId = currencyIds[i]; const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); + account['free'] = this.safeString (balance, 'available'); // https://github.com/ccxt/ccxt/issues/5484 - account['used'] = this.safeFloat (balance, 'orders', 0.0); + account['used'] = this.safeString (balance, 'orders', '0'); const code = this.safeCurrencyCode (currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -47240,11 +47121,11 @@ module.exports = class cex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -47286,12 +47167,12 @@ module.exports = class cex extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const volume = this.safeFloat (ticker, 'volume'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'last'); + const volume = this.safeNumber (ticker, 'volume'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'last'); let symbol = undefined; if (market) { symbol = market['symbol']; @@ -47353,8 +47234,8 @@ module.exports = class cex extends Exchange { const id = this.safeString (trade, 'tid'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -47426,8 +47307,8 @@ module.exports = class cex extends Exchange { // "complete": false // } // - const placedAmount = this.safeFloat (response, 'amount'); - const remaining = this.safeFloat (response, 'pending'); + const placedAmount = this.safeNumber (response, 'amount'); + const remaining = this.safeNumber (response, 'pending'); const timestamp = this.safeValue (response, 'time'); const complete = this.safeValue (response, 'complete'); const status = complete ? 'closed' : 'open'; @@ -47446,7 +47327,7 @@ module.exports = class cex extends Exchange { 'side': this.safeString (response, 'type'), 'symbol': symbol, 'status': status, - 'price': this.safeFloat (response, 'price'), + 'price': this.safeNumber (response, 'price'), 'amount': placedAmount, 'cost': undefined, 'average': undefined, @@ -47488,42 +47369,42 @@ module.exports = class cex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - let amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + let amount = this.safeNumber (order, 'amount'); // sell orders can have a negative amount // https://github.com/ccxt/ccxt/issues/5338 if (amount !== undefined) { amount = Math.abs (amount); } - const remaining = this.safeFloat2 (order, 'pending', 'remains'); + const remaining = this.safeNumber2 (order, 'pending', 'remains'); const filled = amount - remaining; let fee = undefined; let cost = undefined; if (market !== undefined) { symbol = market['symbol']; - const taCost = this.safeFloat (order, 'ta:' + market['quote']); - const ttaCost = this.safeFloat (order, 'tta:' + market['quote']); + const taCost = this.safeNumber (order, 'ta:' + market['quote']); + const ttaCost = this.safeNumber (order, 'tta:' + market['quote']); cost = this.sum (taCost, ttaCost); const baseFee = 'fa:' + market['base']; const baseTakerFee = 'tfa:' + market['base']; const quoteFee = 'fa:' + market['quote']; const quoteTakerFee = 'tfa:' + market['quote']; - let feeRate = this.safeFloat (order, 'tradingFeeMaker'); + let feeRate = this.safeNumber (order, 'tradingFeeMaker'); if (!feeRate) { - feeRate = this.safeFloat (order, 'tradingFeeTaker', feeRate); + feeRate = this.safeNumber (order, 'tradingFeeTaker', feeRate); } if (feeRate) { feeRate /= 100.0; // convert to mathematically-correct percentage coefficients: 1.0 = 100% } if ((baseFee in order) || (baseTakerFee in order)) { - const baseFeeCost = this.safeFloat2 (order, baseFee, baseTakerFee); + const baseFeeCost = this.safeNumber2 (order, baseFee, baseTakerFee); fee = { 'currency': market['base'], 'rate': feeRate, 'cost': baseFeeCost, }; } else if ((quoteFee in order) || (quoteTakerFee in order)) { - const quoteFeeCost = this.safeFloat2 (order, quoteFee, quoteTakerFee); + const quoteFeeCost = this.safeNumber2 (order, quoteFee, quoteTakerFee); fee = { 'currency': market['quote'], 'rate': feeRate, @@ -47563,7 +47444,7 @@ module.exports = class cex extends Exchange { // ds: 0 } continue; } - const tradePrice = this.safeFloat (item, 'price'); + const tradePrice = this.safeNumber (item, 'price'); if (tradePrice === undefined) { // this represents the order // { @@ -47667,8 +47548,8 @@ module.exports = class cex extends Exchange { // "fee_amount": "0.03" // } const tradeTimestamp = this.parse8601 (this.safeString (item, 'time')); - const tradeAmount = this.safeFloat (item, 'amount'); - const feeCost = this.safeFloat (item, 'fee_amount'); + const tradeAmount = this.safeNumber (item, 'amount'); + const feeCost = this.safeNumber (item, 'fee_amount'); let absTradeAmount = (tradeAmount < 0) ? -tradeAmount : tradeAmount; let tradeCost = undefined; if (tradeSide === 'sell') { @@ -48013,12 +47894,12 @@ module.exports = class cex extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const side = this.safeString (order, 'type'); - const baseAmount = this.safeFloat (order, 'a:' + baseId + ':cds'); - const quoteAmount = this.safeFloat (order, 'a:' + quoteId + ':cds'); - const fee = this.safeFloat (order, 'f:' + quoteId + ':cds'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const remaining = this.safeFloat (order, 'remains'); + const baseAmount = this.safeNumber (order, 'a:' + baseId + ':cds'); + const quoteAmount = this.safeNumber (order, 'a:' + quoteId + ':cds'); + const fee = this.safeNumber (order, 'f:' + quoteId + ':cds'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const remaining = this.safeNumber (order, 'remains'); const filled = amount - remaining; let orderAmount = undefined; let cost = undefined; @@ -48030,10 +47911,10 @@ module.exports = class cex extends Exchange { cost = quoteAmount; average = orderAmount / cost; } else { - const ta = this.safeFloat (order, 'ta:' + quoteId, 0); - const tta = this.safeFloat (order, 'tta:' + quoteId, 0); - const fa = this.safeFloat (order, 'fa:' + quoteId, 0); - const tfa = this.safeFloat (order, 'tfa:' + quoteId, 0); + const ta = this.safeNumber (order, 'ta:' + quoteId, 0); + const tta = this.safeNumber (order, 'tta:' + quoteId, 0); + const fa = this.safeNumber (order, 'fa:' + quoteId, 0); + const tfa = this.safeNumber (order, 'tfa:' + quoteId, 0); if (side === 'sell') { cost = this.sum (this.sum (ta, tta), this.sum (fa, tfa)); } else { @@ -48172,47 +48053,14 @@ module.exports = class cex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],60:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const foxbit = require ('./foxbit.js'); - -// --------------------------------------------------------------------------- - -module.exports = class chilebit extends foxbit { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'chilebit', - 'name': 'ChileBit', - 'countries': [ 'CL' ], - 'has': { - 'CORS': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg', - 'api': { - 'public': 'https://api.blinktrade.com/api', - 'private': 'https://api.blinktrade.com/tapi', - }, - 'www': 'https://chilebit.net', - 'doc': 'https://blinktrade.com/docs', - }, - 'options': { - 'brokerId': '9', // https://blinktrade.com/docs/#brokers - }, - }); - } -}; - -},{"./foxbit.js":87}],61:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],60:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, RateLimitExceeded, InvalidNonce } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -48620,10 +48468,10 @@ module.exports = class coinbase extends Exchange { const timestamp = this.parse8601 (this.safeValue (transaction, 'created_at')); const updated = this.parse8601 (this.safeValue (transaction, 'updated_at')); const type = this.safeString (transaction, 'resource'); - const amount = this.safeFloat (subtotalObject, 'amount'); + const amount = this.safeNumber (subtotalObject, 'amount'); const currencyId = this.safeString (subtotalObject, 'currency'); const currency = this.safeCurrencyCode (currencyId); - const feeCost = this.safeFloat (feeObject, 'amount'); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -48699,15 +48547,12 @@ module.exports = class coinbase extends Exchange { const orderId = undefined; const side = this.safeString (trade, 'resource'); const type = undefined; - const cost = this.safeFloat (subtotalObject, 'amount'); - const amount = this.safeFloat (amountObject, 'amount'); - let price = undefined; - if (cost !== undefined) { - if ((amount !== undefined) && (amount > 0)) { - price = cost / amount; - } - } - const feeCost = this.safeFloat (feeObject, 'amount'); + const costString = this.safeString (subtotalObject, 'amount'); + const amountString = this.safeString (amountObject, 'amount'); + const cost = this.parseNumber (costString); + const amount = this.parseNumber (amountString); + const price = this.parseNumber (Precise.stringDiv (costString, amountString)); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -48775,7 +48620,7 @@ module.exports = class coinbase extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (quoteCurrency, 'min_size'), + 'min': this.safeNumber (quoteCurrency, 'min_size'), 'max': undefined, }, }, @@ -48857,7 +48702,7 @@ module.exports = class coinbase extends Exchange { 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min_size'), + 'min': this.safeNumber (currency, 'min_size'), 'max': undefined, }, 'price': { @@ -48888,9 +48733,9 @@ module.exports = class coinbase extends Exchange { const buy = await this.publicGetPricesSymbolBuy (request); const sell = await this.publicGetPricesSymbolSell (request); const spot = await this.publicGetPricesSymbolSpot (request); - const ask = this.safeFloat (buy['data'], 'amount'); - const bid = this.safeFloat (sell['data'], 'amount'); - const last = this.safeFloat (spot['data'], 'amount'); + const ask = this.safeNumber (buy['data'], 'amount'); + const bid = this.safeNumber (sell['data'], 'amount'); + const last = this.safeNumber (spot['data'], 'amount'); return { 'symbol': symbol, 'timestamp': timestamp, @@ -48933,7 +48778,7 @@ module.exports = class coinbase extends Exchange { if (this.inArray (balance['type'], accounts)) { const currencyId = this.safeString (balance['balance'], 'currency'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance['balance'], 'amount'); + const total = this.safeNumber (balance['balance'], 'amount'); const free = total; const used = undefined; if (code in result) { @@ -49234,7 +49079,7 @@ module.exports = class coinbase extends Exchange { // } // const amountInfo = this.safeValue (item, 'amount', {}); - let amount = this.safeFloat (amountInfo, 'amount'); + let amount = this.safeNumber (amountInfo, 'amount'); let direction = undefined; if (amount < 0) { direction = 'out'; @@ -49260,7 +49105,7 @@ module.exports = class coinbase extends Exchange { if (feeInfo !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId, currency); - const feeAmount = this.safeFloat (feeInfo, 'amount'); + const feeAmount = this.safeNumber (feeInfo, 'amount'); fee = { 'cost': feeAmount, 'currency': feeCurrencyCode, @@ -49424,7 +49269,7 @@ module.exports = class coinbase extends Exchange { }; -},{"./base/Exchange":6,"./base/errors":8}],62:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],61:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -49457,7 +49302,7 @@ module.exports = class coinbaseprime extends coinbasepro { } }; -},{"./coinbasepro.js":63}],63:[function(require,module,exports){ +},{"./coinbasepro.js":62}],62:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -49465,6 +49310,7 @@ module.exports = class coinbaseprime extends coinbasepro { const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound, OnMaintenance, PermissionDenied, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -49699,7 +49545,7 @@ module.exports = class coinbasepro extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const details = this.safeValue (currency, 'details', {}); - const precision = this.safeFloat (currency, 'max_precision'); + const precision = this.safeNumber (currency, 'max_precision'); const status = this.safeString (currency, 'status'); const active = (status === 'online'); result[code] = { @@ -49713,7 +49559,7 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (details, 'min_size'), + 'min': this.safeNumber (details, 'min_size'), 'max': undefined, }, 'price': { @@ -49725,7 +49571,7 @@ module.exports = class coinbasepro extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (details, 'min_withdrawal_amount'), + 'min': this.safeNumber (details, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -49769,12 +49615,12 @@ module.exports = class coinbasepro extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const priceLimits = { - 'min': this.safeFloat (market, 'quote_increment'), + 'min': this.safeNumber (market, 'quote_increment'), 'max': undefined, }; const precision = { - 'amount': this.safeFloat (market, 'base_increment'), - 'price': this.safeFloat (market, 'quote_increment'), + 'amount': this.safeNumber (market, 'base_increment'), + 'price': this.safeNumber (market, 'quote_increment'), }; const status = this.safeString (market, 'status'); const active = (status === 'online'); @@ -49788,13 +49634,13 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': priceLimits, 'cost': { - 'min': this.safeFloat (market, 'min_market_funds'), - 'max': this.safeFloat (market, 'max_market_funds'), + 'min': this.safeNumber (market, 'min_market_funds'), + 'max': this.safeNumber (market, 'max_market_funds'), }, }, 'active': active, @@ -49851,14 +49697,13 @@ module.exports = class coinbasepro extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'hold'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'hold'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -49915,29 +49760,29 @@ module.exports = class coinbasepro extends Exchange { // } // const timestamp = this.parse8601 (this.safeValue (ticker, 'time')); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'price'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'price'); const symbol = (market === undefined) ? undefined : market['symbol']; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': undefined, 'ask': ask, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -50010,7 +49855,7 @@ module.exports = class coinbasepro extends Exchange { if (market !== undefined) { const feeCurrencyId = this.safeStringLower (market, 'quoteId'); const costField = feeCurrencyId + '_value'; - cost = this.safeFloat (trade, costField); + cost = this.safeNumber (trade, costField); feeCurrency = market['quote']; const liquidity = this.safeString (trade, 'liquidity'); if (liquidity !== undefined) { @@ -50018,7 +49863,7 @@ module.exports = class coinbasepro extends Exchange { feeRate = market[takerOrMaker]; } } - const feeCost = this.safeFloat2 (trade, 'fill_fees', 'fee'); + const feeCost = this.safeNumber2 (trade, 'fill_fees', 'fee'); const fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -50032,10 +49877,12 @@ module.exports = class coinbasepro extends Exchange { if (orderId !== undefined) { side = (trade['side'] === 'buy') ? 'buy' : 'sell'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - cost = amount * price; + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -50097,11 +49944,11 @@ module.exports = class coinbasepro extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -50181,17 +50028,11 @@ module.exports = class coinbasepro extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'filled_size'); - const amount = this.safeFloat (order, 'size', filled); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'executed_value'); - const feeCost = this.safeFloat (order, 'fill_fees'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'filled_size'); + const amount = this.safeNumber (order, 'size', filled); + const cost = this.safeNumber (order, 'executed_value'); + const feeCost = this.safeNumber (order, 'fill_fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -50209,9 +50050,9 @@ module.exports = class coinbasepro extends Exchange { const side = this.safeString (order, 'side'); const timeInForce = this.safeString (order, 'time_in_force'); const postOnly = this.safeValue (order, 'post_only'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -50229,11 +50070,11 @@ module.exports = class coinbasepro extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -50323,7 +50164,7 @@ module.exports = class coinbasepro extends Exchange { request['client_oid'] = clientOrderId; params = this.omit (params, [ 'clientOrderId', 'client_oid' ]); } - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop_price'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stop_price'); if (stopPrice !== undefined) { request['stop_price'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, [ 'stopPrice', 'stop_price' ]); @@ -50337,7 +50178,7 @@ module.exports = class coinbasepro extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['size'] = this.amountToPrecision (symbol, amount); } else if (type === 'market') { - let cost = this.safeFloat2 (params, 'cost', 'funds'); + let cost = this.safeNumber2 (params, 'cost', 'funds'); if (cost === undefined) { if (price !== undefined) { cost = amount * price; @@ -50408,19 +50249,6 @@ module.exports = class coinbasepro extends Exchange { return await this.privateDeleteOrders (this.extend (request, params)); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - const cost = amount * price; - const currency = market['quote']; - return { - 'type': takerOrMaker, - 'currency': currency, - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (currency, rate * cost)), - }; - } - async fetchPaymentMethods (params = {}) { return await this.privateGetPaymentMethods (params); } @@ -50559,7 +50387,7 @@ module.exports = class coinbasepro extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (transaction); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let type = this.safeString (transaction, 'type'); let address = this.safeString (details, 'crypto_address'); const tag = this.safeString (details, 'destination_tag'); @@ -50568,7 +50396,7 @@ module.exports = class coinbasepro extends Exchange { if (type === 'withdraw') { type = 'withdrawal'; address = this.safeString (details, 'sent_to_address', address); - const feeCost = this.safeFloat (details, 'fee'); + const feeCost = this.safeNumber (details, 'fee'); if (feeCost !== undefined) { if (amount !== undefined) { amount -= feeCost; @@ -50682,13 +50510,14 @@ module.exports = class coinbasepro extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],64:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],63:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -50812,12 +50641,12 @@ module.exports = class coincheck extends Exchange { if (currencyId in balances) { const account = this.account (); const reserved = currencyId + '_reserved'; - account['free'] = this.safeFloat (balances, currencyId); - account['used'] = this.safeFloat (balances, reserved); + account['free'] = this.safeString (balances, currencyId); + account['used'] = this.safeString (balances, reserved); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -50855,23 +50684,13 @@ module.exports = class coincheck extends Exchange { const id = this.safeString (order, 'id'); const side = this.safeString (order, 'order_type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const amount = this.safeFloat (order, 'pending_amount'); - const remaining = this.safeFloat (order, 'pending_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = Math.max (amount - remaining, 0); - if (price !== undefined) { - cost = filled * price; - } - } - } + const amount = this.safeNumber (order, 'pending_amount'); + const remaining = this.safeNumber (order, 'pending_amount'); + const price = this.safeNumber (order, 'rate'); const status = undefined; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -50879,7 +50698,7 @@ module.exports = class coincheck extends Exchange { 'lastTradeTimestamp': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'side': side, 'type': undefined, 'timeInForce': undefined, @@ -50888,12 +50707,12 @@ module.exports = class coincheck extends Exchange { 'symbol': symbol, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'info': order, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -50917,16 +50736,16 @@ module.exports = class coincheck extends Exchange { }; const ticker = await this.publicGetTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -50936,7 +50755,7 @@ module.exports = class coincheck extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -50945,7 +50764,7 @@ module.exports = class coincheck extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'rate'); + const priceString = this.safeString (trade, 'rate'); const marketId = this.safeString (trade, 'pair'); market = this.safeValue (this.markets_by_id, marketId, market); let symbol = undefined; @@ -50972,7 +50791,7 @@ module.exports = class coincheck extends Exchange { } } let takerOrMaker = undefined; - let amount = undefined; + let amountString = undefined; let cost = undefined; let side = undefined; let fee = undefined; @@ -50984,24 +50803,22 @@ module.exports = class coincheck extends Exchange { takerOrMaker = 'maker'; } const funds = this.safeValue (trade, 'funds', {}); - amount = this.safeFloat (funds, baseId); - cost = this.safeFloat (funds, quoteId); + amountString = this.safeString (funds, baseId); + cost = this.safeNumber (funds, quoteId); fee = { 'currency': this.safeString (trade, 'fee_currency'), - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), }; side = this.safeString (trade, 'side'); orderId = this.safeString (trade, 'order_id'); } else { - amount = this.safeFloat (trade, 'amount'); + amountString = this.safeString (trade, 'amount'); side = this.safeString (trade, 'order_type'); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -51072,6 +50889,10 @@ module.exports = class coincheck extends Exchange { return await this.privateDeleteExchangeOrdersId (this.extend (request, params)); } + nonce () { + return this.milliseconds (); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { let url = this.urls['api'] + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); @@ -51118,13 +50939,14 @@ module.exports = class coincheck extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],65:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],64:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -51335,8 +51157,8 @@ module.exports = class coinegg extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; let change = undefined; let average = undefined; @@ -51350,11 +51172,11 @@ module.exports = class coinegg extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -51364,8 +51186,8 @@ module.exports = class coinegg extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVol'), 'info': ticker, }; } @@ -51394,15 +51216,12 @@ module.exports = class coinegg extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const type = 'limit'; const side = this.safeString (trade, 'type'); const id = this.safeString (trade, 'tid'); @@ -51449,9 +51268,9 @@ module.exports = class coinegg extends Exchange { result[code] = this.account (); } const type = (accountType === 'lock') ? 'used' : 'free'; - result[code][type] = this.safeFloat (balances, key); + result[code][type] = this.safeString (balances, key); } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -51460,15 +51279,9 @@ module.exports = class coinegg extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let status = this.safeString (order, 'status'); if (status === 'cancelled') { status = 'canceled'; @@ -51479,7 +51292,7 @@ module.exports = class coinegg extends Exchange { const type = 'limit'; const side = this.safeString (order, 'type'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -51495,13 +51308,13 @@ module.exports = class coinegg extends Exchange { 'stopPrice': undefined, 'cost': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'trades': undefined, 'fee': undefined, 'info': info, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -51637,13 +51450,14 @@ module.exports = class coinegg extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],66:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],65:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, OrderNotFound, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -51836,13 +51650,13 @@ module.exports = class coinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': this.safeFloat (market, 'taker_fee_rate'), - 'maker': this.safeFloat (market, 'maker_fee_rate'), + 'taker': this.safeNumber (market, 'taker_fee_rate'), + 'maker': this.safeNumber (market, 'maker_fee_rate'), 'info': market, 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -51862,16 +51676,16 @@ module.exports = class coinex extends Exchange { symbol = market['symbol']; } ticker = this.safeValue (ticker, 'ticker', {}); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -51881,7 +51695,7 @@ module.exports = class coinex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat2 (ticker, 'vol', 'volume'), + 'baseVolume': this.safeNumber2 (ticker, 'vol', 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -51941,16 +51755,18 @@ module.exports = class coinex extends Exchange { } const tradeId = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market); - let cost = this.safeFloat (trade, 'deal_money'); - if (!cost) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); + let cost = this.safeNumber (trade, 'deal_money'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_asset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -52003,11 +51819,11 @@ module.exports = class coinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -52068,11 +51884,11 @@ module.exports = class coinex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -52111,11 +51927,11 @@ module.exports = class coinex extends Exchange { // } // const timestamp = this.safeTimestamp (order, 'create_time'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'deal_money'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'deal_amount'); - const average = this.safeFloat (order, 'avg_price'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'deal_money'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'deal_amount'); + const average = this.safeNumber (order, 'avg_price'); let symbol = undefined; const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); @@ -52127,11 +51943,11 @@ module.exports = class coinex extends Exchange { feeCurrency = market['quote']; } } - const remaining = this.safeFloat (order, 'left'); + const remaining = this.safeNumber (order, 'left'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -52153,10 +51969,10 @@ module.exports = class coinex extends Exchange { 'trades': undefined, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'deal_fee'), + 'cost': this.safeNumber (order, 'deal_fee'), }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -52402,8 +52218,8 @@ module.exports = class coinex extends Exchange { const timestamp = this.safeTimestamp (transaction, 'create_time'); const type = ('coin_withdraw_id' in transaction) ? 'withdraw' : 'deposit'; const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'tx_fee'); + let amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'tx_fee'); if (type === 'deposit') { feeCost = 0; } @@ -52594,13 +52410,14 @@ module.exports = class coinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],67:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],66:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, RateLimitExceeded, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -52733,11 +52550,11 @@ module.exports = class coinfalcon extends Exchange { 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'change_in_24h'), + 'change': this.safeNumber (ticker, 'change_in_24h'), 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -52774,20 +52591,17 @@ module.exports = class coinfalcon extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } const tradeId = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'order_id'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = this.safeString (trade, 'fee_currency_code'); fee = { @@ -52855,14 +52669,13 @@ module.exports = class coinfalcon extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available_balance'), - 'used': this.safeFloat (balance, 'hold_balance'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'hold_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -52897,19 +52710,9 @@ module.exports = class coinfalcon extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'size_filled'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (price !== undefined) { - cost = filled * price; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'size_filled'); const status = this.parseOrderStatus (this.safeString (order, 'status')); let type = this.safeString (order, 'operation_type'); if (type !== undefined) { @@ -52918,7 +52721,7 @@ module.exports = class coinfalcon extends Exchange { } const side = this.safeString (order, 'order_type'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -52931,16 +52734,16 @@ module.exports = class coinfalcon extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'lastTradeTimestamp': undefined, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -53050,13 +52853,14 @@ module.exports = class coinfalcon extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],68:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],67:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ExchangeError, InvalidNonce, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -53158,14 +52962,14 @@ module.exports = class coinfloor extends Exchange { const baseIdLower = this.safeStringLower (market, 'baseId'); const quoteIdLower = this.safeStringLower (market, 'quoteId'); result[base] = { - 'free': this.safeFloat (response, baseIdLower + '_available'), - 'used': this.safeFloat (response, baseIdLower + '_reserved'), - 'total': this.safeFloat (response, baseIdLower + '_balance'), + 'free': this.safeNumber (response, baseIdLower + '_available'), + 'used': this.safeNumber (response, baseIdLower + '_reserved'), + 'total': this.safeNumber (response, baseIdLower + '_balance'), }; result[quote] = { - 'free': this.safeFloat (response, quoteIdLower + '_available'), - 'used': this.safeFloat (response, quoteIdLower + '_reserved'), - 'total': this.safeFloat (response, quoteIdLower + '_balance'), + 'free': this.safeNumber (response, quoteIdLower + '_available'), + 'used': this.safeNumber (response, quoteIdLower + '_reserved'), + 'total': this.safeNumber (response, quoteIdLower + '_balance'), }; return this.parseBalance (result); } @@ -53186,22 +52990,22 @@ module.exports = class coinfloor extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -53230,14 +53034,11 @@ module.exports = class coinfloor extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -53355,8 +53156,8 @@ module.exports = class coinfloor extends Exchange { const parts = key.split ('_'); const numParts = parts.length; if (numParts === 2) { - const tmpBaseAmount = this.safeFloat (item, parts[0]); - const tmpQuoteAmount = this.safeFloat (item, parts[1]); + const tmpBaseAmount = this.safeNumber (item, parts[0]); + const tmpQuoteAmount = this.safeNumber (item, parts[1]); if (tmpBaseAmount !== undefined && tmpQuoteAmount !== undefined) { baseId = parts[0]; quoteId = parts[1]; @@ -53372,7 +53173,7 @@ module.exports = class coinfloor extends Exchange { const referenceId = this.safeString (item, 'id'); const timestamp = this.parse8601 (this.safeString (item, 'datetime')); let fee = undefined; - const feeCost = this.safeFloat (item, 'fee'); + const feeCost = this.safeNumber (item, 'fee'); const result = { 'id': undefined, 'timestamp': timestamp, @@ -53476,8 +53277,8 @@ module.exports = class coinfloor extends Exchange { 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, 'type': type, - 'price': this.safeFloat (response, 'price'), - 'remaining': this.safeFloat (response, 'amount'), + 'price': this.safeNumber (response, 'price'), + 'remaining': this.safeNumber (response, 'amount'), 'info': response, }; } @@ -53502,19 +53303,14 @@ module.exports = class coinfloor extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let side = undefined; const status = this.safeString (order, 'status'); - if (order['type'] === 0) { + const rawType = this.safeString (order, 'type'); + if (rawType === '0') { side = 'buy'; - } else if (order['type'] === 1) { + } else if (rawType === '1') { side = 'sell'; } let symbol = undefined; @@ -53522,7 +53318,7 @@ module.exports = class coinfloor extends Exchange { symbol = market['symbol']; } const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -53540,11 +53336,11 @@ module.exports = class coinfloor extends Exchange { 'amount': undefined, 'filled': undefined, 'remaining': amount, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -53603,13 +53399,14 @@ module.exports = class coinfloor extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],69:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],68:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -53771,14 +53568,14 @@ module.exports = class coingi extends Exchange { const currencyId = this.safeString (balance['currency'], 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - const blocked = this.safeFloat (balance, 'blocked'); - const inOrders = this.safeFloat (balance, 'inOrders'); - const withdrawing = this.safeFloat (balance, 'withdrawing'); - account['used'] = this.sum (blocked, inOrders, withdrawing); + account['free'] = this.safeString (balance, 'available'); + const blocked = this.safeString (balance, 'blocked'); + const inOrders = this.safeString (balance, 'inOrders'); + const withdrawing = this.safeString (balance, 'withdrawing'); + account['used'] = Precise.stringAdd (Precise.stringAdd (blocked, inOrders), withdrawing); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = 512, params = {}) { @@ -53804,11 +53601,11 @@ module.exports = class coingi extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -53818,8 +53615,8 @@ module.exports = class coingi extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'counterVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'counterVolume'), 'info': ticker, }; } @@ -53852,14 +53649,11 @@ module.exports = class coingi extends Exchange { } parseTrade (trade, market = undefined) { - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const id = this.safeString (trade, 'id'); const marketId = this.safeString (trade, 'currencyPair'); @@ -53953,7 +53747,7 @@ module.exports = class coingi extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],70:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],69:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -54164,16 +53958,16 @@ module.exports = class coinmarketcap extends Exchange { if (timestamp === undefined) { timestamp = this.milliseconds (); } - const change = this.safeFloat (ticker, 'percent_change_24h'); + const change = this.safeNumber (ticker, 'percent_change_24h'); let last = undefined; let symbol = undefined; let volume = undefined; if (market !== undefined) { symbol = market['symbol']; const priceKey = 'price_' + market['quoteId']; - last = this.safeFloat (ticker, priceKey); + last = this.safeNumber (ticker, priceKey); const volumeKey = '24h_volume_' + market['quoteId']; - volume = this.safeFloat (ticker, volumeKey); + volume = this.safeNumber (ticker, volumeKey); } return { 'symbol': symbol, @@ -54302,13 +54096,14 @@ module.exports = class coinmarketcap extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],71:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],70:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder, OrderNotFound, RateLimitExceeded, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -54535,7 +54330,7 @@ module.exports = class coinmate extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -54563,12 +54358,12 @@ module.exports = class coinmate extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -54591,16 +54386,16 @@ module.exports = class coinmate extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'data'); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'vwap': undefined, 'askVolume': undefined, 'open': undefined, @@ -54610,7 +54405,7 @@ module.exports = class coinmate extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'amount'), + 'baseVolume': this.safeNumber (ticker, 'amount'), 'quoteVolume': undefined, 'info': ticker, }; @@ -54679,8 +54474,8 @@ module.exports = class coinmate extends Exchange { // } // const timestamp = this.safeInteger (item, 'timestamp'); - const amount = this.safeFloat (item, 'amount'); - const fee = this.safeFloat (item, 'fee'); + const amount = this.safeNumber (item, 'amount'); + const fee = this.safeNumber (item, 'fee'); const txid = this.safeString (item, 'txid'); const address = this.safeString (item, 'destination'); const tag = this.safeString (item, 'destinationTag'); @@ -54758,21 +54553,18 @@ module.exports = class coinmate extends Exchange { // const marketId = this.safeString (trade, 'currencyPair'); market = this.safeMarket (marketId, market, '_'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeStringLower2 (trade, 'type', 'tradeType'); const type = this.safeStringLower (trade, 'orderType'); const orderId = this.safeString (trade, 'orderId'); const id = this.safeString (trade, 'transactionId'); const timestamp = this.safeInteger2 (trade, 'timestamp', 'createdTimestamp'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -54913,11 +54705,11 @@ module.exports = class coinmate extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.safeInteger (order, 'timestamp'); const side = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'originalAmount'); - let remaining = this.safeFloat (order, 'remainingAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'originalAmount'); + let remaining = this.safeNumber (order, 'remainingAmount'); if (remaining === undefined) { - remaining = this.safeFloat (order, 'amount'); + remaining = this.safeNumber (order, 'amount'); } let status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.parseOrderType (this.safeString (order, 'orderTradeType')); @@ -54932,11 +54724,11 @@ module.exports = class coinmate extends Exchange { cost = filled * price; } } - const average = this.safeFloat (order, 'avgPrice'); + const average = this.safeNumber (order, 'avgPrice'); const marketId = this.safeString (order, 'currencyPair'); const symbol = this.safeSymbol (marketId, market, '_'); const clientOrderId = this.safeString (order, 'clientOrderId'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); return { 'id': id, 'clientOrderId': clientOrderId, @@ -55064,13 +54856,14 @@ module.exports = class coinmate extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],72:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],71:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, BadRequest, ExchangeError, ArgumentsRequired, OrderNotFound, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -55209,11 +55002,11 @@ module.exports = class coinone extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'avail'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -55266,13 +55059,13 @@ module.exports = class coinone extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const first = this.safeFloat (ticker, 'first'); - const last = this.safeFloat (ticker, 'last'); + const first = this.safeNumber (ticker, 'first'); + const last = this.safeNumber (ticker, 'last'); let average = undefined; if (first !== undefined && last !== undefined) { average = this.sum (first, last) / 2; } - const previousClose = this.safeFloat (ticker, 'yesterday_last'); + const previousClose = this.safeNumber (ticker, 'yesterday_last'); let change = undefined; let percentage = undefined; if (last !== undefined && previousClose !== undefined) { @@ -55286,8 +55079,8 @@ module.exports = class coinone extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -55300,7 +55093,7 @@ module.exports = class coinone extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -55346,20 +55139,17 @@ module.exports = class coinone extends Exchange { side = 'buy'; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'fee'); + let feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); - let feeRate = this.safeFloat (trade, 'feeRate'); + let feeRate = this.safeNumber (trade, 'feeRate'); feeRate = Math.abs (feeRate); let feeCurrencyCode = undefined; if (market !== undefined) { @@ -55519,7 +55309,7 @@ module.exports = class coinone extends Exchange { // } // const id = this.safeString (order, 'orderId'); - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); const timestamp = this.safeTimestamp (order, 'timestamp'); let side = this.safeString (order, 'type'); if (side === 'ask') { @@ -55527,9 +55317,8 @@ module.exports = class coinone extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const remaining = this.safeFloat (order, 'remainQty'); - let filled = undefined; - const amount = this.safeFloat (order, 'qty'); + const remaining = this.safeNumber (order, 'remainQty'); + const amount = this.safeNumber (order, 'qty'); let status = this.safeString (order, 'status'); // https://github.com/ccxt/ccxt/pull/7067 if (status === 'live') { @@ -55539,14 +55328,7 @@ module.exports = class coinone extends Exchange { } } } - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (amount - remaining); - } status = this.parseOrderStatus (status); - let cost = undefined; - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } let symbol = undefined; let base = undefined; let quote = undefined; @@ -55566,16 +55348,16 @@ module.exports = class coinone extends Exchange { quote = market['quote']; } let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = (side === 'sell') ? quote : base; fee = { 'cost': feeCost, - 'rate': this.safeFloat (order, 'feeRate'), + 'rate': this.safeNumber (order, 'feeRate'), 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -55589,15 +55371,15 @@ module.exports = class coinone extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': amount, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -55672,8 +55454,8 @@ module.exports = class coinone extends Exchange { // eslint-disable-next-line quotes throw new ArgumentsRequired (this.id + " cancelOrder() requires a symbol argument. To cancel the order, pass a symbol argument and {'price': 12345, 'qty': 1.2345, 'is_ask': 0} in the params argument of cancelOrder."); } - const price = this.safeFloat (params, 'price'); - const qty = this.safeFloat (params, 'qty'); + const price = this.safeNumber (params, 'price'); + const qty = this.safeNumber (params, 'qty'); const isAsk = this.safeInteger (params, 'is_ask'); if ((price === undefined) || (qty === undefined) || (isAsk === undefined)) { // eslint-disable-next-line quotes @@ -55748,13 +55530,14 @@ module.exports = class coinone extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],73:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],72:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -55874,7 +55657,7 @@ module.exports = class coinspot extends Exchange { const balance = currencies[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } } @@ -55884,11 +55667,11 @@ module.exports = class coinspot extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -55908,16 +55691,16 @@ module.exports = class coinspot extends Exchange { id = id.toLowerCase (); const ticker = response['prices'][id]; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -55965,11 +55748,13 @@ module.exports = class coinspot extends Exchange { // "market":"BTC/AUD" // } // - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'total'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger (trade, 'solddate'); const marketId = this.safeString (trade, 'market'); @@ -56037,13 +55822,15 @@ module.exports = class coinspot extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],74:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],73:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, InvalidNonce, RequestTimeout, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, AuthenticationError, BadSymbol } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -56150,6 +55937,7 @@ module.exports = class crex24 extends Exchange { ], }, }, + 'precisionMode': TICK_SIZE, 'fees': { 'trading': { 'tierBased': true, @@ -56170,6 +55958,7 @@ module.exports = class crex24 extends Exchange { 'BIT': 'BitMoney', 'BULL': 'BuySell', 'CREDIT': 'TerraCredit', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'GHOST': 'GHOSTPRISM', 'IQ': 'IQ.Cash', 'PUT': 'PutinCoin', @@ -56203,6 +55992,7 @@ module.exports = class crex24 extends Exchange { 'API Key': AuthenticationError, // "API Key '9edc48de-d5b0-4248-8e7e-f59ffcd1c7f1' doesn't exist." 'Insufficient funds': InsufficientFunds, // "Insufficient funds: new order requires 10 ETH which is more than the available balance." 'has been delisted.': BadSymbol, // {"errorDescription":"Instrument '$PAC-BTC' has been delisted."} + 'is currently suspended.': BadSymbol, // {"errorDescription":"Trading in BITG-BTC is currently suspended."} 'Mandatory parameter': BadRequest, // {"errorDescription":"Mandatory parameter 'feeCurrency' is missing."} }, }, @@ -56244,12 +56034,12 @@ module.exports = class crex24 extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const tickSize = this.safeValue (market, 'tickSize'); - const minPrice = this.safeValue (market, 'minPrice'); - const minAmount = this.safeFloat (market, 'minVolume'); + const tickSize = this.safeNumber (market, 'tickSize'); + const minPrice = this.safeNumber (market, 'minPrice'); + const minAmount = this.safeNumber (market, 'minVolume'); const precision = { - 'amount': this.precisionFromString (this.numberToString (minAmount)), - 'price': this.precisionFromString (this.numberToString (tickSize)), + 'amount': minAmount, + 'price': tickSize, }; const active = (market['state'] === 'active'); result.push ({ @@ -56314,7 +56104,8 @@ module.exports = class crex24 extends Exchange { const currency = response[i]; const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); - const precision = this.safeInteger (currency, 'withdrawalPrecision'); + const withdrawalPrecision = this.safeInteger (currency, 'withdrawalPrecision'); + const precision = Math.pow (10, -withdrawalPrecision); const address = this.safeValue (currency, 'BaseAddress'); const active = (currency['depositsAllowed'] && currency['withdrawalsAllowed'] && !currency['isDelisted']); const type = currency['isFiat'] ? 'fiat' : 'crypto'; @@ -56326,7 +56117,7 @@ module.exports = class crex24 extends Exchange { 'type': type, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'flatWithdrawalFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'flatWithdrawalFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -56342,12 +56133,12 @@ module.exports = class crex24 extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -56377,11 +56168,11 @@ module.exports = class crex24 extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -56433,16 +56224,16 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); const marketId = this.safeString (ticker, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -56450,10 +56241,10 @@ module.exports = class crex24 extends Exchange { 'last': last, 'previousClose': undefined, // previous day close 'change': undefined, - 'percentage': this.safeFloat (ticker, 'percentChange'), + 'percentage': this.safeNumber (ticker, 'percentChange'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -56523,14 +56314,6 @@ module.exports = class crex24 extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - parseTrade (trade, market = undefined) { // // public fetchTrades @@ -56555,14 +56338,11 @@ module.exports = class crex24 extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'orderId'); @@ -56571,7 +56351,7 @@ module.exports = class crex24 extends Exchange { let fee = undefined; const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCode = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -56632,11 +56412,11 @@ module.exports = class crex24 extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -56705,50 +56485,19 @@ module.exports = class crex24 extends Exchange { const marketId = this.safeString (order, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remainingVolume'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remainingVolume'); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'lastUpdate')); - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = amount - remaining; - if (this.options['parseOrderToPrecision']) { - filled = parseFloat (this.amountToPrecision (symbol, filled)); - } - filled = Math.max (filled, 0.0); - if (price !== undefined) { - cost = price * filled; - } - } - } const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeString (order, 'side'); const fee = undefined; const trades = undefined; - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const average = undefined; const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -56762,14 +56511,14 @@ module.exports = class crex24 extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -56804,7 +56553,7 @@ module.exports = class crex24 extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -57223,8 +56972,8 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'createdAt')); const updated = this.parse8601 (this.safeString (transaction, 'processedAt')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); const fee = { 'cost': feeCost, 'currency': code, @@ -57349,14 +57098,15 @@ module.exports = class crex24 extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],75:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],74:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -57444,6 +57194,7 @@ module.exports = class currencycom extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.002, @@ -57602,7 +57353,7 @@ module.exports = class currencycom extends Exchange { const filtersByType = this.indexBy (filters, 'filterType'); const precision = { 'amount': 1 / Math.pow (1, this.safeInteger (market, 'baseAssetPrecision')), - 'price': this.safeFloat (market, 'tickSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'TRADING'); @@ -57635,14 +57386,14 @@ module.exports = class currencycom extends Exchange { 'max': undefined, }, 'cost': { - 'min': -1 * Math.log10 (precision['amount']), + 'min': -Math.log10 (precision['amount']), 'max': undefined, }, }, }; - const exchangeFee = this.safeFloat2 (market, 'exchangeFee', 'tradingFee'); - const makerFee = this.safeFloat (market, 'makerFee', exchangeFee); - const takerFee = this.safeFloat (market, 'takerFee', exchangeFee); + const exchangeFee = this.safeNumber2 (market, 'exchangeFee', 'tradingFee'); + const makerFee = this.safeNumber (market, 'makerFee', exchangeFee); + const takerFee = this.safeNumber (market, 'takerFee', exchangeFee); if (makerFee !== undefined) { entry['maker'] = makerFee / 100; } @@ -57651,65 +57402,44 @@ module.exports = class currencycom extends Exchange { } if ('PRICE_FILTER' in filtersByType) { const filter = this.safeValue (filtersByType, 'PRICE_FILTER', {}); - entry['precision']['price'] = this.safeFloat (filter, 'tickSize'); + entry['precision']['price'] = this.safeNumber (filter, 'tickSize'); // PRICE_FILTER reports zero values for maxPrice // since they updated filter types in November 2018 // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } } if ('LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'LOT_SIZE', {}); - entry['precision']['amount'] = this.safeFloat (filter, 'stepSize'); + entry['precision']['amount'] = this.safeNumber (filter, 'stepSize'); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat (filter, 'minNotional'); + entry['limits']['cost']['min'] = this.safeNumber (filter, 'minNotional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { const response = await this.privateGetAccount (params); // @@ -57756,8 +57486,8 @@ module.exports = class currencycom extends Exchange { const response = await this.privateGetAccount (params); return { 'info': response, - 'maker': this.safeFloat (response, 'makerCommission'), - 'taker': this.safeFloat (response, 'takerCommission'), + 'maker': this.safeNumber (response, 'makerCommission'), + 'taker': this.safeNumber (response, 'takerCommission'), }; } @@ -57791,11 +57521,11 @@ module.exports = class currencycom extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -57894,8 +57624,8 @@ module.exports = class currencycom extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); - const open = this.safeFloat (ticker, 'openPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); let average = undefined; if ((open !== undefined) && (last !== undefined)) { average = this.sum (open, last) / 2; @@ -57904,22 +57634,22 @@ module.exports = class currencycom extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), 'open': open, 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -57954,14 +57684,6 @@ module.exports = class currencycom extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24hr (params); @@ -57994,11 +57716,11 @@ module.exports = class currencycom extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -58064,8 +57786,11 @@ module.exports = class currencycom extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -58081,7 +57806,7 @@ module.exports = class currencycom extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -58103,7 +57828,7 @@ module.exports = class currencycom extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': fee, }; } @@ -58179,66 +57904,21 @@ module.exports = class currencycom extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); + const remaining = undefined; + const cost = this.safeNumber (order, 'cummulativeQuoteQty'); const id = this.safeString (order, 'orderId'); const type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeStringLower (order, 'side'); - let fee = undefined; let trades = undefined; const fills = this.safeValue (order, 'fills'); if (fills !== undefined) { trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'timestamp': timestamp, @@ -58252,13 +57932,13 @@ module.exports = class currencycom extends Exchange { 'stopPrice': undefined, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -58470,7 +58150,7 @@ module.exports = class currencycom extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],76:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],75:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -58478,6 +58158,7 @@ module.exports = class currencycom extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, BadRequest, BadSymbol, InvalidOrder, AuthenticationError, ArgumentsRequired, OrderNotFound, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -58731,14 +58412,14 @@ module.exports = class delta extends Exchange { 'name': this.safeString (currency, 'name'), 'info': currency, // the original payload 'active': active, - 'fee': this.safeFloat (currency, 'base_withdrawal_fee'), + 'fee': this.safeNumber (currency, 'base_withdrawal_fee'), 'precision': 1 / Math.pow (10, precision), 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal_amount'), + 'min': this.safeNumber (currency, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -58872,26 +58553,26 @@ module.exports = class delta extends Exchange { } const precision = { 'amount': 1.0, // number of contracts - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; const limits = { 'amount': { 'min': 1.0, - 'max': this.safeFloat (market, 'position_size_limit'), + 'max': this.safeNumber (market, 'position_size_limit'), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; const state = this.safeString (market, 'state'); const active = (state === 'live'); - const maker = this.safeFloat (market, 'maker_commission_rate'); - const taker = this.safeFloat (market, 'taker_commission_rate'); + const maker = this.safeNumber (market, 'maker_commission_rate'); + const taker = this.safeNumber (market, 'taker_commission_rate'); result.push ({ 'id': id, 'numericId': numericId, @@ -58939,8 +58620,8 @@ module.exports = class delta extends Exchange { const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.001); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; let percentage = undefined; @@ -58951,15 +58632,15 @@ module.exports = class delta extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'turnover'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'turnover'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -59129,12 +58810,11 @@ module.exports = class delta extends Exchange { const orderId = this.safeString (trade, 'order_id'); let timestamp = this.parse8601 (this.safeString (trade, 'created_at')); timestamp = this.safeIntegerProduct (trade, 'timestamp', 0.001, timestamp); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const product = this.safeValue (trade, 'product', {}); const marketId = this.safeString (product, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -59153,7 +58833,7 @@ module.exports = class delta extends Exchange { if (type !== undefined) { type = type.replace ('_order', ''); } - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { const settlingAsset = this.safeValue (product, 'settling_asset', {}); @@ -59220,11 +58900,11 @@ module.exports = class delta extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -59294,11 +58974,11 @@ module.exports = class delta extends Exchange { const currency = this.safeValue (currenciesByNumericId, currencyId); const code = (currency === undefined) ? currencyId : currency['code']; const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchPosition (symbol, params = undefined) { @@ -59322,7 +59002,7 @@ module.exports = class delta extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPositionsMargined (params); // @@ -59403,20 +59083,12 @@ module.exports = class delta extends Exchange { const side = this.safeString (order, 'side'); let type = this.safeString (order, 'order_type'); type = type.replace ('_order', ''); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'unfilled_size'); - let filled = undefined; - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let cost = undefined; - const average = this.safeFloat (order, 'average_fill_price'); - if ((average !== undefined) && filled) { - cost = average * filled; - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'unfilled_size'); + const average = this.safeNumber (order, 'average_fill_price'); let fee = undefined; - const feeCost = this.safeFloat (order, 'paid_commission'); + const feeCost = this.safeNumber (order, 'paid_commission'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -59429,7 +59101,7 @@ module.exports = class delta extends Exchange { 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -59441,14 +59113,14 @@ module.exports = class delta extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -59847,9 +59519,9 @@ module.exports = class delta extends Exchange { const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId'); currency = this.safeValue (currenciesByNumericId, currencyId, currency); const code = (currency === undefined) ? undefined : currency['code']; - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'created_at')); - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const before = Math.max (0, after - amount); const status = 'ok'; return { @@ -59955,7 +59627,7 @@ module.exports = class delta extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],77:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],76:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -59963,6 +59635,7 @@ module.exports = class delta extends Exchange { const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, DDoSProtection, NotSupported, ExchangeNotAvailable, InsufficientFunds, BadRequest, InvalidAddress, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -60393,8 +60066,8 @@ module.exports = class deribit extends Exchange { const future = (type === 'future'); const option = (type === 'option'); const active = this.safeValue (market, 'is_active'); - const minTradeAmount = this.safeFloat (market, 'min_trade_amount'); - const tickSize = this.safeFloat (market, 'tick_size'); + const minTradeAmount = this.safeNumber (market, 'min_trade_amount'); + const tickSize = this.safeNumber (market, 'tick_size'); const precision = { 'amount': minTradeAmount, 'price': tickSize, @@ -60406,8 +60079,8 @@ module.exports = class deribit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_commission'), - 'maker': this.safeFloat (market, 'maker_commission'), + 'taker': this.safeNumber (market, 'taker_commission'), + 'maker': this.safeNumber (market, 'maker_commission'), 'limits': { 'amount': { 'min': minTradeAmount, @@ -60490,11 +60163,11 @@ module.exports = class deribit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const currencyCode = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableFunds'); - account['used'] = this.safeFloat (balance, 'maintenanceMargin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'maintenanceMargin'); + account['total'] = this.safeString (balance, 'equity'); result[currencyCode] = account; - return this.parseBalance (result); + return this.parseBalance (result, false); } async createDepositAddress (code, params = {}) { @@ -60612,18 +60285,18 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger2 (ticker, 'timestamp', 'creation_timestamp'); const marketId = this.safeString (ticker, 'instrument_name'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat2 (ticker, 'last_price', 'last'); + const last = this.safeNumber2 (ticker, 'last_price', 'last'); const stats = this.safeValue (ticker, 'stats', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (stats, 'high', 'max_price'), - 'low': this.safeFloat2 (stats, 'low', 'min_price'), - 'bid': this.safeFloat2 (ticker, 'best_bid_price', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_amount'), - 'ask': this.safeFloat2 (ticker, 'best_ask_price', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_amount'), + 'high': this.safeNumber2 (stats, 'high', 'max_price'), + 'low': this.safeNumber2 (stats, 'low', 'min_price'), + 'bid': this.safeNumber2 (ticker, 'best_bid_price', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_amount'), + 'ask': this.safeNumber2 (ticker, 'best_ask_price', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_amount'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -60633,7 +60306,7 @@ module.exports = class deribit extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (stats, 'volume'), + 'quoteVolume': this.safeNumber (stats, 'volume'), 'info': ticker, }; } @@ -60820,21 +60493,18 @@ module.exports = class deribit extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const liquidity = this.safeString (trade, 'liquidity'); let takerOrMaker = undefined; if (liquidity !== undefined) { // M = maker, T = taker, MT = both takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -61014,31 +60684,21 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger (order, 'creation_timestamp'); const lastUpdate = this.safeInteger (order, 'last_update_timestamp'); const id = this.safeString (order, 'order_id'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); let lastTradeTimestamp = undefined; if (filled !== undefined) { if (filled > 0) { lastTradeTimestamp = lastUpdate; } } - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = price * filled; - } - } const status = this.parseOrderStatus (this.safeString (order, 'order_state')); const marketId = this.safeString (order, 'instrument_name'); market = this.safeMarket (marketId, market); const side = this.safeStringLower (order, 'direction'); - let feeCost = this.safeFloat (order, 'commission'); + let feeCost = this.safeNumber (order, 'commission'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); @@ -61056,7 +60716,7 @@ module.exports = class deribit extends Exchange { const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); const stopPrice = this.safeValue (order, 'stop_price'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -61071,14 +60731,14 @@ module.exports = class deribit extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -61155,7 +60815,7 @@ module.exports = class deribit extends Exchange { } } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price or stopPrice param for a ' + type + ' order'); } else { @@ -61554,7 +61214,7 @@ module.exports = class deribit extends Exchange { const updated = this.safeInteger (transaction, 'updated_timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let type = 'deposit'; let fee = undefined; if (feeCost !== undefined) { @@ -61577,7 +61237,7 @@ module.exports = class deribit extends Exchange { 'tagTo': undefined, 'tagFrom': undefined, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -61623,7 +61283,7 @@ module.exports = class deribit extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.codeFromOptions ('fetchPositions'); const currency = this.currency (code); @@ -61744,13 +61404,14 @@ module.exports = class deribit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],78:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],77:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); -const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -61808,11 +61469,6 @@ module.exports = class digifinex extends Exchange { 'referral': 'https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp', }, 'api': { - 'v2': { - 'get': [ - 'ticker', - ], - }, 'public': { 'get': [ '{market}/symbols', @@ -61938,6 +61594,7 @@ module.exports = class digifinex extends Exchange { }, 'commonCurrencies': { 'BHT': 'Black House Test', + 'EPS': 'Epanus', 'MBN': 'Mobilian Coin', 'TEL': 'TEL666', }, @@ -61992,7 +61649,7 @@ module.exports = class digifinex extends Exchange { const depositStatus = this.safeValue (currency, 'deposit_status', 1); const withdrawStatus = this.safeValue (currency, 'withdraw_status', 1); const active = depositStatus && withdrawStatus; - const fee = this.safeFloat (currency, 'withdraw_fee_rate'); + const fee = this.safeNumber (currency, 'withdraw_fee_rate'); if (code in result) { if (Array.isArray (result[code]['info'])) { result[code]['info'].push (currency); @@ -62023,7 +61680,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw_amount'), + 'min': this.safeNumber (currency, 'min_withdraw_amount'), 'max': undefined, }, }, @@ -62077,7 +61734,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), 'max': undefined, }, 'price': { @@ -62085,7 +61742,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), + 'min': this.safeNumber (market, 'minimum_value'), 'max': undefined, }, }; @@ -62099,7 +61756,7 @@ module.exports = class digifinex extends Exchange { // const status = this.safeString (market, 'status'); // const active = (status === 'TRADING'); // - const isAllowed = this.safeValue (market, 'is_allow', 1); + const isAllowed = this.safeInteger (market, 'is_allow', 1); const active = isAllowed ? true : false; const type = 'spot'; const spot = (type === 'spot'); @@ -62155,7 +61812,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), + 'min': this.safeNumber (market, 'min_volume'), 'max': undefined, }, 'price': { @@ -62163,7 +61820,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, }; @@ -62208,12 +61865,12 @@ module.exports = class digifinex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -62247,87 +61904,67 @@ module.exports = class digifinex extends Exchange { } async fetchTickers (symbols = undefined, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTickers() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); - const request = { - 'apiKey': apiKey, - }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (params); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const result = {}; - const tickers = this.safeValue (response, 'ticker', {}); + const tickers = this.safeValue (response, 'ticker', []); const date = this.safeInteger (response, 'date'); - const reversedMarketIds = Object.keys (tickers); - for (let i = 0; i < reversedMarketIds.length; i++) { - const reversedMarketId = reversedMarketIds[i]; - const ticker = this.extend ({ + for (let i = 0; i < tickers.length; i++) { + const rawTicker = this.extend ({ 'date': date, - }, tickers[reversedMarketId]); - const [ quoteId, baseId ] = reversedMarketId.split ('_'); - const marketId = baseId.toUpperCase () + '_' + quoteId.toUpperCase (); - const market = this.safeMarket (marketId, undefined, '_'); - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); + }, tickers[i]); + const ticker = this.parseTicker (rawTicker); + const symbol = ticker['symbol']; + result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTicker (symbol, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTicker() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); const market = this.market (symbol); - // reversed base/quote in v2 - const marketId = market['quoteId'].toLowerCase () + '_' + market['baseId'].toLowerCase (); const request = { - 'symbol': marketId, - 'apiKey': apiKey, + 'symbol': market['id'], }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (this.extend (request, params)); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const date = this.safeInteger (response, 'date'); - const ticker = this.safeValue (response, 'ticker', {}); - let result = this.safeValue (ticker, marketId, {}); - result = this.extend ({ 'date': date }, result); + const tickers = this.safeValue (response, 'ticker', []); + const firstTicker = this.safeValue (tickers, 0, {}); + const result = this.extend ({ 'date': date }, firstTicker); return this.parseTicker (result, market); } @@ -62337,6 +61974,7 @@ module.exports = class digifinex extends Exchange { // // { // "last":0.021957, + // "symbol": "btc_usdt", // "base_vol":2249.3521732227, // "change":-0.6, // "vol":102443.5111, @@ -62347,22 +61985,20 @@ module.exports = class digifinex extends Exchange { // "date"1564518452, // injected from fetchTicker/fetchTickers // } // - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeStringUpper (ticker, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -62372,8 +62008,8 @@ module.exports = class digifinex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'base_vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'base_vol'), 'info': ticker, }; } @@ -62409,18 +62045,15 @@ module.exports = class digifinex extends Exchange { const orderId = this.safeString (trade, 'order_id'); const timestamp = this.safeTimestamp2 (trade, 'date', 'timestamp'); const side = this.safeString2 (trade, 'type', 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); const takerOrMaker = this.safeValue (trade, 'is_maker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -62522,11 +62155,11 @@ module.exports = class digifinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 5), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 1), // volume + this.safeNumber (ohlcv, 5), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 1), // volume ]; } @@ -62717,21 +62350,11 @@ module.exports = class digifinex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_price'); - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - return { + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -62747,13 +62370,13 @@ module.exports = class digifinex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'average': average, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -62947,7 +62570,7 @@ module.exports = class digifinex extends Exchange { const code = this.safeCurrencyCode (this.safeString (item, 'currency_mark'), currency); const timestamp = this.safeTimestamp (item, 'time'); const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -63010,16 +62633,6 @@ module.exports = class digifinex extends Exchange { return this.parseLedger (items, currency, since, limit); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -63172,8 +62785,8 @@ module.exports = class digifinex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_date')); const updated = this.parse8601 (this.safeString (transaction, 'finished_date')); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -63223,7 +62836,7 @@ module.exports = class digifinex extends Exchange { } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const version = (api === 'v2') ? api : this.version; + const version = this.version; let url = this.urls['api'] + '/' + version + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); const urlencoded = this.urlencode (this.keysort (query)); @@ -63275,1283 +62888,7 @@ module.exports = class digifinex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],79:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, BadRequest, InsufficientFunds, PermissionDenied, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class dsx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'dsx', - 'name': 'DSX', - 'countries': [ 'UK' ], - 'rateLimit': 1500, - 'version': 'v3', - 'has': { - 'cancelOrder': true, - 'CORS': false, - 'createDepositAddress': true, - 'createMarketOrder': false, - 'createOrder': true, - 'fetchBalance': true, - 'fetchClosedOrders': false, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOHLCV': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchOrderBooks': true, - 'fetchOrders': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTransactions': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg', - 'api': { - 'public': 'https://dsxglobal.com/mapi', // market data - 'private': 'https://dsxglobal.com/tapi', // trading - 'dwapi': 'https://dsxglobal.com/dwapi', // deposit/withdraw - }, - 'www': 'https://dsxglobal.com', - 'doc': [ - 'https://dsxglobal.com/developers/publicApi', - ], - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'maker': 0.15 / 100, - 'taker': 0.25 / 100, - }, - }, - 'timeframes': { - '1m': 'm', - '1h': 'h', - '1d': 'd', - }, - 'api': { - // market data (public) - 'public': { - 'get': [ - 'barsFromMoment/{pair}/{period}/{start}', - 'depth/{pair}', - 'info', - 'lastBars/{pair}/{period}/{amount}', // period is 'm', 'h' or 'd' - 'periodBars/{pair}/{period}/{start}/{end}', - 'ticker/{pair}', - 'trades/{pair}', - ], - }, - // trading (private) - 'private': { - 'post': [ - 'info/account', - 'history/transactions', - 'history/trades', - 'history/orders', - 'orders', - 'order/cancel', - // 'order/cancel/all', - 'order/status', - 'order/new', - 'volume', - 'fees', // trading fee schedule - ], - }, - // deposit / withdraw (private) - 'dwapi': { - 'post': [ - 'deposit/cryptoaddress', - 'withdraw/crypto', - 'withdraw/fiat', - 'withdraw/submit', - // 'withdraw/cancel', - 'transaction/status', // see 'history/transactions' in private tapi above - ], - }, - }, - 'exceptions': { - 'exact': { - 'Sign is invalid': AuthenticationError, // {"success":0,"error":"Sign is invalid"} - 'Order was rejected. Incorrect price.': InvalidOrder, // {"success":0,"error":"Order was rejected. Incorrect price."} - "Order was rejected. You don't have enough money.": InsufficientFunds, // {"success":0,"error":"Order was rejected. You don't have enough money."} - 'This method is blocked for your pair of keys': PermissionDenied, // {"success":0,"error":"This method is blocked for your pair of keys"} - }, - 'broad': { - 'INVALID_PARAMETER': BadRequest, - 'Invalid pair name': ExchangeError, // {"success":0,"error":"Invalid pair name: btc_eth"} - 'invalid api key': AuthenticationError, - 'invalid sign': AuthenticationError, - 'api key dont have trade permission': AuthenticationError, - 'invalid parameter': InvalidOrder, - 'invalid order': InvalidOrder, - 'Requests too often': DDoSProtection, - 'not available': ExchangeNotAvailable, - 'data unavailable': ExchangeNotAvailable, - 'external service unavailable': ExchangeNotAvailable, - 'nonce is invalid': InvalidNonce, // {"success":0,"error":"Parameter: nonce is invalid"} - 'Incorrect volume': InvalidOrder, // {"success": 0,"error":"Order was rejected. Incorrect volume."} - }, - }, - 'options': { - 'fetchTickersMaxLength': 250, - }, - 'commonCurrencies': { - 'DSH': 'DASH', - }, - }); - } - - async fetchMarkets (params = {}) { - const response = await this.publicGetInfo (params); - // - // { - // "server_time": 1522057909, - // "pairs": { - // "ethusd": { - // "decimal_places": 5, - // "min_price": 100, - // "max_price": 1500, - // "min_amount": 0.01, - // "hidden": 0, - // "fee": 0, - // "amount_decimal_places": 4, - // "quoted_currency": "USD", - // "base_currency": "ETH" - // } - // } - // } - // - const markets = this.safeValue (response, 'pairs'); - const keys = Object.keys (markets); - const result = []; - for (let i = 0; i < keys.length; i++) { - const id = keys[i]; - const market = markets[id]; - const baseId = this.safeString (market, 'base_currency'); - const quoteId = this.safeString (market, 'quoted_currency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const precision = { - 'amount': this.safeInteger (market, 'decimal_places'), - 'price': this.safeInteger (market, 'decimal_places'), - }; - const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), - }; - const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), - }; - const costLimits = { - 'min': this.safeFloat (market, 'min_total'), - }; - const limits = { - 'amount': amountLimits, - 'price': priceLimits, - 'cost': costLimits, - }; - const hidden = this.safeInteger (market, 'hidden'); - const active = (hidden === 0); - // see parseMarket below - // https://github.com/ccxt/ccxt/pull/5786 - const otherId = base.toLowerCase () + quote.toLowerCase (); - result.push ({ - 'id': id, - 'otherId': otherId, // https://github.com/ccxt/ccxt/pull/5786 - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': active, - 'precision': precision, - 'limits': limits, - 'info': market, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostInfoAccount (); - // - // { - // "success" : 1, - // "return" : { - // "funds" : { - // "BTC" : { - // "total" : 0, - // "available" : 0 - // }, - // "USD" : { - // "total" : 0, - // "available" : 0 - // }, - // "USDT" : { - // "total" : 0, - // "available" : 0 - // } - // }, - // "rights" : { - // "info" : 1, - // "trade" : 1 - // }, - // "transactionCount" : 0, - // "openOrders" : 0, - // "serverTime" : 1537451465 - // } - // } - // - const balances = this.safeValue (response, 'return'); - const result = { 'info': response }; - const funds = this.safeValue (balances, 'funds'); - const currencyIds = Object.keys (funds); - for (let i = 0; i < currencyIds.length; i++) { - const currencyId = currencyIds[i]; - const code = this.safeCurrencyCode (currencyId); - const balance = this.safeValue (funds, currencyId, {}); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseTicker (ticker, market = undefined) { - // - // { high: 0.03492, - // low: 0.03245, - // avg: 29.46133, - // vol: 500.8661, - // vol_cur: 17.000797104, - // last: 0.03364, - // buy: 0.03362, - // sell: 0.03381, - // updated: 1537521993, - // pair: "ethbtc" } - // - const timestamp = this.safeTimestamp (ticker, 'updated'); - let symbol = undefined; - const marketId = this.safeString (ticker, 'pair'); - market = this.parseMarket (marketId); - if (market !== undefined) { - symbol = market['symbol']; - } - // dsx average is inverted, liqui average is not - let average = this.safeFloat (ticker, 'avg'); - if (average !== undefined) { - if (average > 0) { - average = 1 / average; - } - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_cur'), - 'info': ticker, - }; - } - - parseTrade (trade, market = undefined) { - // - // fetchTrades (public) - // - // { - // "amount" : 0.0128, - // "price" : 6483.99000, - // "timestamp" : 1540334614, - // "tid" : 35684364, - // "type" : "ask" - // } - // - // fetchMyTrades (private) - // - // { - // "number": "36635882", // <-- this is present if the trade has come from the '/order/status' call - // "id": "36635882", // <-- this may have been artifically added by the parseTrades method - // "pair": "btcusd", - // "type": "buy", - // "volume": 0.0595, - // "rate": 9750, - // "orderId": 77149299, - // "timestamp": 1519612317, - // "commission": 0.00020825, - // "commissionCurrency": "btc" - // } - // - const timestamp = this.safeTimestamp (trade, 'timestamp'); - let side = this.safeString (trade, 'type'); - if (side === 'ask') { - side = 'sell'; - } else if (side === 'bid') { - side = 'buy'; - } - const price = this.safeFloat2 (trade, 'rate', 'price'); - const id = this.safeString2 (trade, 'number', 'id'); - const orderId = this.safeString (trade, 'orderId'); - const marketId = this.safeString (trade, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const amount = this.safeFloat2 (trade, 'amount', 'volume'); - const type = 'limit'; // all trades are still limit trades - let takerOrMaker = undefined; - let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const isYourOrder = this.safeValue (trade, 'is_your_order'); - if (isYourOrder !== undefined) { - takerOrMaker = 'taker'; - if (isYourOrder) { - takerOrMaker = 'maker'; - } - if (fee === undefined) { - fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); - } - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - return { - 'id': id, - 'order': orderId, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': type, - 'side': side, - 'takerOrMaker': takerOrMaker, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - 'info': trade, - }; - } - - parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - let result = []; - if (Array.isArray (trades)) { - for (let i = 0; i < trades.length; i++) { - result.push (this.parseTrade (trades[i], market)); - } - } else { - const ids = Object.keys (trades); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const trade = this.parseTrade (trades[id], market); - result.push (this.extend (trade, { 'id': id }, params)); - } - } - result = this.sortBy (result, 'timestamp'); - const symbol = (market !== undefined) ? market['symbol'] : undefined; - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const market_id_in_reponse = (market['id'] in response); - if (!market_id_in_reponse) { - throw new ExchangeError (this.id + ' ' + market['symbol'] + ' order book is empty or not available'); - } - const orderbook = response[market['id']]; - return this.parseOrderBook (orderbook); - } - - async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let ids = undefined; - if (symbols === undefined) { - ids = this.ids.join ('-'); - // max URL length is 2083 symbols, including http schema, hostname, tld, etc... - if (ids.length > 2048) { - const numIds = this.ids.length; - throw new ExchangeError (this.id + ' has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const result = {}; - ids = Object.keys (response); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let symbol = id; - if (id in this.markets_by_id) { - const market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseOrderBook (response[id]); - } - return result; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - let ids = this.ids; - if (symbols === undefined) { - const numIds = ids.length; - ids = ids.join ('-'); - const maxLength = this.safeInteger (this.options, 'fetchTickersMaxLength', 2048); - // max URL length is 2048 symbols, including http schema, hostname, tld, etc... - if (ids.length > this.options['fetchTickersMaxLength']) { - throw new ArgumentsRequired (this.id + ' has ' + numIds.toString () + ' markets exceeding max URL length for this endpoint (' + maxLength.toString () + ' characters), please, specify a list of symbols of interest in the first argument to fetchTickers'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - const tickers = await this.publicGetTickerPair (this.extend (request, params)); - // - // { - // "bchbtc" : { - // "high" : 0.02989, - // "low" : 0.02736, - // "avg" : 33.90585, - // "vol" : 0.65982205, - // "vol_cur" : 0.0194604180960, - // "last" : 0.03000, - // "buy" : 0.02980, - // "sell" : 0.03001, - // "updated" : 1568104614, - // "pair" : "bchbtc" - // }, - // "ethbtc" : { - // "high" : 0.01772, - // "low" : 0.01742, - // "avg" : 56.89082, - // "vol" : 229.247115044, - // "vol_cur" : 4.02959737298943, - // "last" : 0.01769, - // "buy" : 0.01768, - // "sell" : 0.01776, - // "updated" : 1568104614, - // "pair" : "ethbtc" - // } - // } - // - const result = {}; - const keys = Object.keys (tickers); - for (let k = 0; k < keys.length; k++) { - const id = keys[k]; - const ticker = tickers[id]; - let symbol = id; - let market = undefined; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseTicker (ticker, market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - const tickers = await this.fetchTickers ([ symbol ], params); - return tickers[symbol]; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; - } - const response = await this.publicGetTradesPair (this.extend (request, params)); - if (Array.isArray (response)) { - const numElements = response.length; - if (numElements === 0) { - return []; - } - } - return this.parseTrades (response[market['id']], market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // } - // - return [ - this.safeInteger (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - 'period': this.timeframes[timeframe], - }; - let method = 'publicGetLastBarsPairPeriodAmount'; - if (since === undefined) { - if (limit === undefined) { - limit = 100; // required, max 2000 - } - request['amount'] = limit; - } else { - method = 'publicGetPeriodBarsPairPeriodStartEnd'; - // in their docs they expect milliseconds - // but it returns empty arrays with milliseconds - // however, it does work properly with seconds - request['start'] = parseInt (since / 1000); - if (limit === undefined) { - request['end'] = this.seconds (); - } else { - const duration = this.parseTimeframe (timeframe) * 1000; - const end = this.sum (since, duration * limit); - request['end'] = parseInt (end / 1000); - } - } - const response = await this[method] (this.extend (request, params)); - // - // { - // "ethbtc": [ - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // }, - // { - // "high" : 0.01967, - // "open" : 0.01967, - // "low" : 0.01967, - // "close" : 0.01967, - // "amount" : 0, - // "timestamp" : 1565155680000 - // } - // ] - // } - // - const candles = this.safeValue (response, market['id'], []); - return this.parseOHLCVs (candles, market, timeframe, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (type === 'market' && price === undefined) { - throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument even for market orders, that is the worst price that you agree to fill your order for'); - } - const request = { - 'pair': market['id'], - 'type': side, - 'volume': this.amountToPrecision (symbol, amount), - 'rate': this.priceToPrecision (symbol, price), - 'orderType': type, - }; - price = parseFloat (price); - amount = parseFloat (amount); - const response = await this.privatePostOrderNew (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "received": 0, - // "remains": 10, - // "funds": { - // "BTC": { - // "total": 100, - // "available": 95 - // }, - // "USD": { - // "total": 10000, - // "available": 9995 - // }, - // "EUR": { - // "total": 1000, - // "available": 995 - // }, - // "LTC": { - // "total": 1000, - // "available": 995 - // } - // }, - // "orderId": 0, // https://github.com/ccxt/ccxt/issues/3677 - // } - // } - // - let status = 'open'; - let filled = 0.0; - let remaining = amount; - const responseReturn = this.safeValue (response, 'return'); - let id = this.safeString2 (responseReturn, 'orderId', 'order_id'); - if (id === '0') { - id = this.safeString (responseReturn, 'initOrderId', 'init_order_id'); - status = 'closed'; - } - filled = this.safeFloat (responseReturn, 'received', 0.0); - remaining = this.safeFloat (responseReturn, 'remains', amount); - const timestamp = this.milliseconds (); - return { - 'info': response, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'side': side, - 'price': price, - 'cost': price * filled, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'fee': undefined, - // 'trades': this.parseTrades (order['trades'], market), - }; - } - - parseOrderStatus (status) { - const statuses = { - '0': 'open', // Active - '1': 'closed', // Filled - '2': 'canceled', // Killed - '3': 'canceling', // Killing - '7': 'canceled', // Rejected - }; - return this.safeString (statuses, status, status); - } - - parseMarket (id) { - if (id in this.markets_by_id) { - return this.markets_by_id[id]; - } else { - // the following is a fix for - // https://github.com/ccxt/ccxt/pull/5786 - // https://github.com/ccxt/ccxt/issues/5770 - let markets_by_other_id = this.safeValue (this.options, 'markets_by_other_id'); - if (markets_by_other_id === undefined) { - this.options['markets_by_other_id'] = this.indexBy (this.markets, 'otherId'); - markets_by_other_id = this.options['markets_by_other_id']; - } - if (id in markets_by_other_id) { - return markets_by_other_id[id]; - } - } - return undefined; - } - - parseOrder (order, market = undefined) { - // - // fetchOrder - // - // { - // "number": 36635882, - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // - const id = this.safeString (order, 'id'); - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const timestamp = this.safeTimestamp (order, 'timestampCreated'); - const marketId = this.safeString (order, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const remaining = this.safeFloat (order, 'remainingVolume'); - const amount = this.safeFloat (order, 'volume'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } - } - const orderType = this.safeString (order, 'orderType'); - const side = this.safeString (order, 'type'); - let fee = undefined; - const deals = this.safeValue (order, 'deals', []); - const numDeals = deals.length; - let trades = undefined; - let lastTradeTimestamp = undefined; - if (numDeals > 0) { - trades = this.parseTrades (deals); - let feeCost = undefined; - let feeCurrency = undefined; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - if (feeCost === undefined) { - feeCost = 0; - } - feeCost = this.sum (feeCost, trade['fee']['cost']); - feeCurrency = trade['fee']['currency']; - lastTradeTimestamp = trade['timestamp']; - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'type': orderType, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': undefined, - 'cost': cost, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'status': status, - 'fee': fee, - 'trades': trades, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': parseInt (id), - }; - const response = await this.privatePostOrderStatus (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // } - // - return this.parseOrder (this.extend ({ - 'id': id, - }, response['return'])); - } - - parseOrdersById (orders, symbol = undefined, since = undefined, limit = undefined) { - const ids = Object.keys (orders); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.parseOrder (this.extend ({ - 'id': id.toString (), - }, orders[id])); - result.push (order); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - const response = await this.privatePostOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': id, - }; - const response = await this.privatePostOrderCancel (this.extend (request, params)); - return response; - } - - parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { - const result = []; - const ids = Object.keys (orders); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.extend ({ 'id': id }, orders[id]); - result.push (this.extend (this.parseOrder (order, market), params)); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - const orders = await this.fetchOrders (symbol, since, limit, params); - return this.filterBy (orders, 'status', 'closed'); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let market = undefined; - // some derived classes use camelcase notation for request fields - const request = { - // 'from': 123456789, // trade ID, from which the display starts numerical 0 (test result: liqui ignores this field) - // 'count': 1000, // the number of trades for display numerical, default = 1000 - // 'from_id': trade ID, from which the display starts numerical 0 - // 'end_id': trade ID on which the display ends numerical ∞ - // 'order': 'ASC', // sorting, default = DESC (test result: liqui ignores this field, most recent trade always goes last) - // 'since': 1234567890, // UTC start time, default = 0 (test result: liqui ignores this field) - // 'end': 1234567890, // UTC end time, default = ∞ (test result: liqui ignores this field) - // 'pair': 'eth_btc', // default = all markets - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['pair'] = market['id']; - } - if (limit !== undefined) { - request['count'] = parseInt (limit); - } - if (since !== undefined) { - request['since'] = parseInt (since / 1000); - } - const response = await this.privatePostHistoryTrades (this.extend (request, params)); - let trades = []; - if ('return' in response) { - trades = response['return']; - } - return this.parseTrades (trades, market, since, limit); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let currency = undefined; - const request = {}; - if (code !== undefined) { - currency = this.currency (code); - request['currency'] = currency['id']; - } - if (since !== undefined) { - request['since'] = since; - } - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryTransactions (this.extend (request, params)); - // - // { - // "success": 1, - // "return": [ - // { - // "id": 1, - // "timestamp": 11, - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // ] - // } - // - const transactions = this.safeValue (response, 'return', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - '1': 'failed', - '2': 'ok', - '3': 'pending', - '4': 'failed', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // "id": 1, - // "timestamp": 11, // 11 in their docs ( - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // - const timestamp = this.safeTimestamp (transaction, 'timestamp'); - let type = this.safeString (transaction, 'type'); - if (type !== undefined) { - if (type === 'Incoming') { - type = 'deposit'; - } else if (type === 'Withdraw') { - type = 'withdrawal'; - } - } - const currencyId = this.safeString (transaction, 'currency'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - return { - 'id': this.safeString (transaction, 'id'), - 'txid': this.safeString (transaction, 'txid'), - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'address': this.safeString (transaction, 'address'), - 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), - 'currency': code, - 'status': status, - 'fee': { - 'currency': code, - 'cost': this.safeFloat (transaction, 'commission'), - 'rate': undefined, - }, - 'info': transaction, - }; - } - - async createDepositAddress (code, params = {}) { - const request = { - 'new': 1, - }; - const response = await this.fetchDepositAddress (code, this.extend (request, params)); - return response; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency': currency['id'], - }; - const response = await this.dwapiPostDepositCryptoaddress (this.extend (request, params)); - const result = this.safeValue (response, 'return', {}); - const address = this.safeString (result, 'address'); - this.checkAddress (address); - return { - 'currency': code, - 'address': address, - 'tag': undefined, // not documented in DSX API - 'info': response, - }; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - const commission = this.safeValue (params, 'commission'); - if (commission === undefined) { - throw new ArgumentsRequired (this.id + ' withdraw() requires a `commission` (withdrawal fee) parameter (string)'); - } - params = this.omit (params, commission); - const request = { - 'currency': currency['id'], - 'amount': parseFloat (amount), - 'address': address, - 'commission': commission, - }; - if (tag !== undefined) { - request['address'] += ':' + tag; - } - const response = await this.dwapiPostWithdrawCrypto (this.extend (request, params)); - // - // [ - // { - // "success": 1, - // "return": { - // "transactionId": 2863073 - // } - // } - // ] - // - const data = this.safeValue (response, 'return', {}); - const id = this.safeString (data, 'transactionId'); - return { - 'info': response, - 'id': id, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'][api]; - const query = this.omit (params, this.extractParams (path)); - if (api === 'private' || api === 'dwapi') { - url += '/' + this.version + '/' + this.implodeParams (path, params); - this.checkRequiredCredentials (); - const nonce = this.nonce (); - body = this.urlencode (this.extend ({ - 'nonce': nonce, - }, query)); - const signature = this.hmac (this.encode (body), this.encode (this.secret), 'sha512', 'base64'); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': signature, - }; - } else if (api === 'public') { - url += '/' + this.implodeParams (path, params); - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - url += '/' + this.implodeParams (path, params); - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - if (Object.keys (query).length) { - body = this.json (query); - headers = { - 'Content-Type': 'application/json', - }; - } - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - if ('success' in response) { - // - // 1 - Liqui only returns the integer 'success' key from their private API - // - // { "success": 1, ... } httpCode === 200 - // { "success": 0, ... } httpCode === 200 - // - // 2 - However, exchanges derived from Liqui, can return non-integers - // - // It can be a numeric string - // { "sucesss": "1", ... } - // { "sucesss": "0", ... }, httpCode >= 200 (can be 403, 502, etc) - // - // Or just a string - // { "success": "true", ... } - // { "success": "false", ... }, httpCode >= 200 - // - // Or a boolean - // { "success": true, ... } - // { "success": false, ... }, httpCode >= 200 - // - // 3 - Oversimplified, Python PEP8 forbids comparison operator (===) of different types - // - // 4 - We do not want to copy-paste and duplicate the code of this handler to other exchanges derived from Liqui - // - // To cover points 1, 2, 3 and 4 combined this handler should work like this: - // - let success = this.safeValue (response, 'success', false); - if (typeof success === 'string') { - if ((success === 'true') || (success === '1')) { - success = true; - } else { - success = false; - } - } - if (!success) { - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'error'); - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],80:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],78:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -64775,7 +63112,7 @@ module.exports = class equos extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeVol'), + 'min': this.safeNumber (market, 'minTradeVol'), 'max': undefined, }, 'price': { @@ -64841,7 +63178,7 @@ module.exports = class equos extends Exchange { const name = this.safeString (currency, 6); const status = this.safeInteger (currency, 4); const active = (status === 1); - const fee = this.safeFloat (currency, 5); // withdraw_fee + const fee = this.safeNumber (currency, 5); // withdraw_fee return { 'id': id, 'info': currency, @@ -64933,8 +63270,8 @@ module.exports = class equos extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); return [ this.convertFromScale (price, market['precision']['price']), this.convertFromScale (amount, market['precision']['amount']), @@ -65080,9 +63417,9 @@ module.exports = class equos extends Exchange { orderId = this.safeString (trade, 'orderId'); side = this.safeStringLower (trade, 'side'); type = this.parseOrderType (this.safeString (trade, 'ordType')); - price = this.safeFloat (trade, 'lastPx'); - amount = this.safeFloat (trade, 'quoteQty'); - let feeCost = this.safeFloat (trade, 'commission'); + price = this.safeNumber (trade, 'lastPx'); + amount = this.safeNumber (trade, 'quoteQty'); + let feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { feeCost = -feeCost; const feeCurrencyId = this.safeString (trade, 'commCurrency'); @@ -65153,8 +63490,8 @@ module.exports = class equos extends Exchange { if (assetType === 'ASSET') { const currencyId = this.safeString (position, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const quantity = this.safeFloat (position, 'quantity'); - const availableQuantity = this.safeFloat (position, 'availableQuantity'); + const quantity = this.safeNumber (position, 'quantity'); + const availableQuantity = this.safeNumber (position, 'availableQuantity'); const scale = this.safeInteger (position, 'quantity_scale'); const account = this.account (); account['free'] = this.convertFromScale (availableQuantity, scale); @@ -65200,7 +63537,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -65297,7 +63634,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -65670,7 +64007,7 @@ module.exports = class equos extends Exchange { address = undefined; } const type = this.safeString (transaction, 'type'); - let amount = this.safeFloat (transaction, 'balance_change'); + let amount = this.safeNumber (transaction, 'balance_change'); if (amount === undefined) { amount = this.safeInteger (transaction, 'quantity'); const amountScale = this.safeInteger (transaction, 'quantity_scale'); @@ -65753,8 +64090,8 @@ module.exports = class equos extends Exchange { for (let i = 0; i < tradingFees.length; i++) { const tradingFee = tradingFees[i]; if (this.safeString (tradingFee, 'tier') !== undefined) { - taker[tradingFee['tier']] = this.safeFloat (tradingFee, 'taker'); - maker[tradingFee['tier']] = this.safeFloat (tradingFee, 'maker'); + taker[tradingFee['tier']] = this.safeNumber (tradingFee, 'taker'); + maker[tradingFee['tier']] = this.safeNumber (tradingFee, 'maker'); } } return { @@ -65885,28 +64222,6 @@ module.exports = class equos extends Exchange { let remaining = this.safeInteger (order, 'leavesQty'); const remainingScale = this.safeInteger (order, 'leavesQty_scale'); remaining = this.convertFromScale (remaining, remainingScale); - if (remaining <= 0) { - if ((filled !== undefined) && (amount !== undefined) && (filled < amount)) { - remaining = undefined; - } - } - if ((remaining === undefined) && (amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0); - } - let average = this.safeInteger (order, 'price', 0); - if (average === 0) { - average = undefined; - } - const averageScale = this.safeInteger (order, 'price_scale'); - average = this.convertFromScale (average, averageScale); - let cost = undefined; - if (filled !== 0) { - if (average > 0) { - cost = average * filled; - } else if (price > 0) { - cost = price * filled; - } - } let fee = undefined; const currencyId = this.safeInteger (order, 'feeInstrumentId'); const feeCurrencyCode = this.safeCurrencyCode (currencyId); @@ -65929,7 +64244,7 @@ module.exports = class equos extends Exchange { } const stopPriceScale = this.safeInteger (order, 'stopPx_scale', 0); const stopPrice = this.convertFromScale (this.safeInteger (order, 'stopPx'), stopPriceScale); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -65944,14 +64259,14 @@ module.exports = class equos extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -66101,7 +64416,7 @@ module.exports = class equos extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],81:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],79:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -66109,6 +64424,7 @@ module.exports = class equos extends Exchange { const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, InvalidOrder, ExchangeError, BadRequest, BadSymbol } = require ('./base/errors'); const { TRUNCATE, SIGNIFICANT_DIGITS } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -66321,7 +64637,7 @@ module.exports = class eterbase extends Exchange { const rule = rules[i]; const attribute = this.safeString (rule, 'attribute'); const condition = this.safeString (rule, 'condition'); - const value = this.safeFloat (rule, 'value'); + const value = this.safeNumber (rule, 'value'); if ((attribute === 'Qty') && (condition === 'Min')) { minAmount = value; } else if ((attribute === 'Qty') && (condition === 'Max')) { @@ -66411,7 +64727,7 @@ module.exports = class eterbase extends Exchange { 'type': type, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -66427,8 +64743,8 @@ module.exports = class eterbase extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMin'), - 'max': this.safeFloat (currency, 'withdrawalMax'), + 'min': this.safeNumber (currency, 'withdrawalMin'), + 'max': this.safeNumber (currency, 'withdrawalMax'), }, }, }; @@ -66455,17 +64771,17 @@ module.exports = class eterbase extends Exchange { const marketId = this.safeString (ticker, 'marketId'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const last = this.safeFloat (ticker, 'price'); - const baseVolume = this.safeFloat (ticker, 'volumeBase'); - const quoteVolume = this.safeFloat (ticker, 'volume'); + const last = this.safeNumber (ticker, 'price'); + const baseVolume = this.safeNumber (ticker, 'volumeBase'); + const quoteVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const percentage = this.safeFloat (ticker, 'change'); + const percentage = this.safeNumber (ticker, 'change'); const result = { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -66507,14 +64823,6 @@ module.exports = class eterbase extends Exchange { return this.parseTicker (response, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { @@ -66569,10 +64877,12 @@ module.exports = class eterbase extends Exchange { // "filledAt": 1556355722341 // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -66581,9 +64891,9 @@ module.exports = class eterbase extends Exchange { 'currency': feeCurrencyCode, }; } - let cost = this.safeFloat (trade, 'qty'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + let cost = this.safeNumber (trade, 'qty'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger2 (trade, 'executedAt', 'filledAt'); const tradeSide = this.safeString (trade, 'side'); @@ -66681,11 +64991,11 @@ module.exports = class eterbase extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -66748,14 +65058,13 @@ module.exports = class eterbase extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetId'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'reserved'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -66882,18 +65191,18 @@ module.exports = class eterbase extends Exchange { } else { type = 'stoplimit'; } - let price = this.safeFloat (order, 'limitPrice'); - const amount = this.safeFloat (order, 'qty'); - let remaining = this.safeFloat (order, 'remainingQty'); + let price = this.safeNumber (order, 'limitPrice'); + const amount = this.safeNumber (order, 'qty'); + let remaining = this.safeNumber (order, 'remainingQty'); let filled = undefined; - const remainingCost = this.safeFloat (order, 'remainingCost'); + const remainingCost = this.safeNumber (order, 'remainingCost'); if ((remainingCost !== undefined) && (remainingCost === 0.0)) { remaining = 0; } if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); } - const cost = this.safeFloat (order, 'cost'); + const cost = this.safeNumber (order, 'cost'); if (type === 'market') { if (price === 0.0) { if ((cost !== undefined) && (filled !== undefined)) { @@ -66910,7 +65219,7 @@ module.exports = class eterbase extends Exchange { } } const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -67083,7 +65392,7 @@ module.exports = class eterbase extends Exchange { } if ((uppercaseType === 'MARKET') && (uppercaseSide === 'BUY')) { // for market buy it requires the amount of quote currency to spend - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); if (this.options['createMarketBuyOrderRequiresPrice']) { if (cost === undefined) { if (price !== undefined) { @@ -67246,7 +65555,7 @@ module.exports = class eterbase extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],82:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],80:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -67361,6 +65670,7 @@ module.exports = class exmo extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.2 / 100, @@ -67830,18 +66140,18 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = marketId.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const maxAmount = this.safeFloat (limit, 'max_q'); - const maxPrice = this.safeFloat (limit, 'max_p'); - const maxCost = this.safeFloat (limit, 'max_a'); - const minAmount = this.safeFloat (limit, 'min_q'); - const minPrice = this.safeFloat (limit, 'min_p'); - const minCost = this.safeFloat (limit, 'min_a'); - minAmounts[base] = Math.min (this.safeFloat (minAmounts, base, minAmount), minAmount); - maxAmounts[base] = Math.max (this.safeFloat (maxAmounts, base, maxAmount), maxAmount); - minPrices[quote] = Math.min (this.safeFloat (minPrices, quote, minPrice), minPrice); - minCosts[quote] = Math.min (this.safeFloat (minCosts, quote, minCost), minCost); - maxPrices[quote] = Math.max (this.safeFloat (maxPrices, quote, maxPrice), maxPrice); - maxCosts[quote] = Math.max (this.safeFloat (maxCosts, quote, maxCost), maxCost); + const maxAmount = this.safeNumber (limit, 'max_q'); + const maxPrice = this.safeNumber (limit, 'max_p'); + const maxCost = this.safeNumber (limit, 'max_a'); + const minAmount = this.safeNumber (limit, 'min_q'); + const minPrice = this.safeNumber (limit, 'min_p'); + const minCost = this.safeNumber (limit, 'min_a'); + minAmounts[base] = Math.min (this.safeNumber (minAmounts, base, minAmount), minAmount); + maxAmounts[base] = Math.max (this.safeNumber (maxAmounts, base, maxAmount), maxAmount); + minPrices[quote] = Math.min (this.safeNumber (minPrices, quote, minPrice), minPrice); + minCosts[quote] = Math.min (this.safeNumber (minCosts, quote, minCost), minCost); + maxPrices[quote] = Math.max (this.safeNumber (maxPrices, quote, maxPrice), maxPrice); + maxCosts[quote] = Math.max (this.safeNumber (maxCosts, quote, maxCost), maxCost); } const result = {}; for (let i = 0; i < ids.length; i++) { @@ -67858,16 +66168,16 @@ module.exports = class exmo extends Exchange { 'precision': 8, 'limits': { 'amount': { - 'min': this.safeFloat (minAmounts, code), - 'max': this.safeFloat (maxAmounts, code), + 'min': this.safeNumber (minAmounts, code), + 'max': this.safeNumber (maxAmounts, code), }, 'price': { - 'min': this.safeFloat (minPrices, code), - 'max': this.safeFloat (maxPrices, code), + 'min': this.safeNumber (minPrices, code), + 'max': this.safeNumber (maxPrices, code), }, 'cost': { - 'min': this.safeFloat (minCosts, code), - 'max': this.safeFloat (maxCosts, code), + 'min': this.safeNumber (minCosts, code), + 'max': this.safeNumber (maxCosts, code), }, }, 'info': id, @@ -67902,8 +66212,8 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = symbol.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const taker = this.safeFloat (market, 'commission_taker_percent'); - const maker = this.safeFloat (market, 'commission_maker_percent'); + const taker = this.safeNumber (market, 'commission_taker_percent'); + const maker = this.safeNumber (market, 'commission_maker_percent'); result.push ({ 'id': id, 'symbol': symbol, @@ -67916,16 +66226,16 @@ module.exports = class exmo extends Exchange { 'maker': maker / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, }, 'precision': { @@ -67998,11 +66308,11 @@ module.exports = class exmo extends Exchange { // return [ this.safeInteger (ohlcv, 't'), - this.safeFloat (ohlcv, 'o'), - this.safeFloat (ohlcv, 'h'), - this.safeFloat (ohlcv, 'l'), - this.safeFloat (ohlcv, 'c'), - this.safeFloat (ohlcv, 'v'), + this.safeNumber (ohlcv, 'o'), + this.safeNumber (ohlcv, 'h'), + this.safeNumber (ohlcv, 'l'), + this.safeNumber (ohlcv, 'c'), + this.safeNumber (ohlcv, 'v'), ]; } @@ -68018,14 +66328,14 @@ module.exports = class exmo extends Exchange { const currencyId = this.currencyId (code); const account = this.account (); if (currencyId in free) { - account['free'] = this.safeFloat (free, currencyId); + account['free'] = this.safeString (free, currencyId); } if (currencyId in used) { - account['used'] = this.safeFloat (used, currencyId); + account['used'] = this.safeString (used, currencyId); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -68083,16 +66393,16 @@ module.exports = class exmo extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -68101,9 +66411,9 @@ module.exports = class exmo extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_curr'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'vol_curr'), 'info': ticker, }; } @@ -68164,9 +66474,9 @@ module.exports = class exmo extends Exchange { let symbol = undefined; const id = this.safeString (trade, 'trade_id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'quantity'); + const cost = this.safeNumber (trade, 'amount'); const side = this.safeString (trade, 'type'); const type = undefined; const marketId = this.safeString (trade, 'pair'); @@ -68185,11 +66495,11 @@ module.exports = class exmo extends Exchange { } const takerOrMaker = this.safeString (trade, 'exec_type'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission_amount'); + const feeCost = this.safeNumber (trade, 'commission_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commission_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (trade, 'commission_percent'); + let feeRate = this.safeNumber (trade, 'commission_percent'); if (feeRate !== undefined) { feeRate /= 1000; } @@ -68488,13 +66798,13 @@ module.exports = class exmo extends Exchange { market = this.markets_by_id[marketId]; } } - let amount = this.safeFloat (order, 'quantity'); + let amount = this.safeNumber (order, 'quantity'); if (amount === undefined) { const amountField = (side === 'buy') ? 'in_amount' : 'out_amount'; - amount = this.safeFloat (order, amountField); + amount = this.safeNumber (order, amountField); } - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'amount'); + let price = this.safeNumber (order, 'price'); + let cost = this.safeNumber (order, 'amount'); let filled = 0.0; const trades = []; const transactions = this.safeValue (order, 'trades', []); @@ -68615,24 +66925,6 @@ module.exports = class exmo extends Exchange { return undefined; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -68677,7 +66969,7 @@ module.exports = class exmo extends Exchange { // } // const timestamp = this.safeTimestamp (transaction, 'dt'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -68707,7 +66999,7 @@ module.exports = class exmo extends Exchange { // fixed funding fees only (for now) if (!this.fees['funding']['percentage']) { const key = (type === 'withdrawal') ? 'withdraw' : 'deposit'; - let feeCost = this.safeFloat (this.options['fundingFees'][key], code); + let feeCost = this.safeNumber (this.options['fundingFees'][key], code); // users don't pay for cashbacks, no fees for that const provider = this.safeString (transaction, 'provider'); if (provider === 'cashback') { @@ -68854,13 +67146,14 @@ module.exports = class exmo extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],83:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],81:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ExchangeNotAvailable, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -69005,26 +67298,26 @@ module.exports = class exx extends Exchange { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); ticker = ticker['ticker']; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'riseRate'), + 'change': this.safeNumber (ticker, 'riseRate'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -69074,14 +67367,11 @@ module.exports = class exx extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -69126,14 +67416,13 @@ module.exports = class exx extends Exchange { const currencyId = currencies[i]; const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'balance'), - 'used': this.safeFloat (balance, 'freeze'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -69153,11 +67442,10 @@ module.exports = class exx extends Exchange { // const symbol = market['symbol']; const timestamp = parseInt (order['trade_date']); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'trade_money'); - const amount = this.safeFloat (order, 'total_amount'); - const filled = this.safeFloat (order, 'trade_amount', 0.0); - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'trade_money'); + const amount = this.safeNumber (order, 'total_amount'); + const filled = this.safeNumber (order, 'trade_amount', 0.0); let status = this.safeInteger (order, 'status'); if (status === 1) { status = 'canceled'; @@ -69169,11 +67457,11 @@ module.exports = class exx extends Exchange { let fee = undefined; if ('fees' in order) { fee = { - 'cost': this.safeFloat (order, 'fees'), + 'cost': this.safeNumber (order, 'fees'), 'currency': market['quote'], }; } - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -69190,12 +67478,12 @@ module.exports = class exx extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -69320,13 +67608,14 @@ module.exports = class exx extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],84:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],82:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, ArgumentsRequired, InsufficientFunds, InvalidOrder, RateLimitExceeded, InvalidNonce, AuthenticationError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -69546,8 +67835,8 @@ module.exports = class fcoin extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'limit_amount_min'), - 'max': this.safeFloat (market, 'limit_amount_max'), + 'min': this.safeNumber (market, 'limit_amount_min'), + 'max': this.safeNumber (market, 'limit_amount_max'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -69642,12 +67931,12 @@ module.exports = class fcoin extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidsAsks (orders, priceKey = 0, amountKey = 1) { @@ -69660,8 +67949,8 @@ module.exports = class fcoin extends Exchange { const priceField = this.sum (index, priceKey); const amountField = this.sum (index, amountKey); result.push ([ - this.safeFloat (orders, priceField), - this.safeFloat (orders, amountField), + this.safeNumber (orders, priceField), + this.safeNumber (orders, amountField), ]); } return result; @@ -69709,17 +67998,17 @@ module.exports = class fcoin extends Exchange { } } const values = ticker['ticker']; - const last = this.safeFloat (values, 0); + const last = this.safeNumber (values, 0); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (values, 7), - 'low': this.safeFloat (values, 8), - 'bid': this.safeFloat (values, 2), - 'bidVolume': this.safeFloat (values, 3), - 'ask': this.safeFloat (values, 4), - 'askVolume': this.safeFloat (values, 5), + 'high': this.safeNumber (values, 7), + 'low': this.safeNumber (values, 8), + 'bid': this.safeNumber (values, 2), + 'bidVolume': this.safeNumber (values, 3), + 'ask': this.safeNumber (values, 4), + 'askVolume': this.safeNumber (values, 5), 'vwap': undefined, 'open': undefined, 'close': last, @@ -69728,8 +68017,8 @@ module.exports = class fcoin extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (values, 9), - 'quoteVolume': this.safeFloat (values, 10), + 'baseVolume': this.safeNumber (values, 9), + 'quoteVolume': this.safeNumber (values, 10), 'info': ticker, }; } @@ -69742,14 +68031,11 @@ module.exports = class fcoin extends Exchange { const timestamp = this.safeInteger (trade, 'ts'); const side = this.safeStringLower (trade, 'side'); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = undefined; return { 'id': id, @@ -69874,38 +68160,25 @@ module.exports = class fcoin extends Exchange { const symbol = market['symbol']; const orderType = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'created_at'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'executed_value'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'executed_value'); let feeCurrency = undefined; let feeCost = undefined; - const feeRebate = this.safeFloat (order, 'fees_income'); + const feeRebate = this.safeNumber (order, 'fees_income'); if ((feeRebate !== undefined) && (feeRebate > 0)) { if (market !== undefined) { feeCurrency = (side === 'buy') ? market['quote'] : market['base']; } feeCost = -feeRebate; } else { - feeCost = this.safeFloat (order, 'fill_fees'); + feeCost = this.safeNumber (order, 'fill_fees'); if (market !== undefined) { feeCurrency = (side === 'buy') ? market['base'] : market['quote']; } } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -69921,7 +68194,7 @@ module.exports = class fcoin extends Exchange { 'stopPrice': undefined, 'cost': cost, 'amount': amount, - 'remaining': remaining, + 'remaining': undefined, 'filled': filled, 'average': undefined, 'status': status, @@ -69930,7 +68203,7 @@ module.exports = class fcoin extends Exchange { 'currency': feeCurrency, }, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -69972,11 +68245,11 @@ module.exports = class fcoin extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_vol'), ]; } @@ -70065,7 +68338,7 @@ module.exports = class fcoin extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],85:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],83:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -70091,13 +68364,14 @@ module.exports = class fcoinjp extends fcoin { } }; -},{"./fcoin.js":84}],86:[function(require,module,exports){ +},{"./fcoin.js":82}],84:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70225,11 +68499,11 @@ module.exports = class flowbtc extends Exchange { const currencyId = balance['name']; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['total'] = this.safeFloat (balance, 'hold'); + account['free'] = this.safeString (balance, 'balance'); + account['total'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -70250,16 +68524,16 @@ module.exports = class flowbtc extends Exchange { }; const ticker = await this.publicPostGetTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -70269,8 +68543,8 @@ module.exports = class flowbtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume24hr'), - 'quoteVolume': this.safeFloat (ticker, 'volume24hrProduct2'), + 'baseVolume': this.safeNumber (ticker, 'volume24hr'), + 'quoteVolume': this.safeNumber (ticker, 'volume24hrProduct2'), 'info': ticker, }; } @@ -70279,14 +68553,11 @@ module.exports = class flowbtc extends Exchange { const timestamp = this.safeTimestamp (trade, 'unixtime'); const side = (trade['incomingOrderSide'] === 0) ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'px'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'px'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'timestamp': timestamp, @@ -70377,13 +68648,14 @@ module.exports = class flowbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],87:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],85:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70469,11 +68741,11 @@ module.exports = class foxbit extends Exchange { // otherwise we will lose the info if the currency balance has been funded or traded or not if (currencyId in balances) { const account = this.account (); - let used = this.safeFloat (balances, currencyId + '_locked'); + let used = this.safeNumber (balances, currencyId + '_locked'); if (used !== undefined) { used *= 1e-8; } - let total = this.safeFloat (balances, currencyId); + let total = this.safeNumber (balances, currencyId); if (total !== undefined) { total *= 1e-8; } @@ -70508,16 +68780,16 @@ module.exports = class foxbit extends Exchange { const timestamp = this.milliseconds (); const lowercaseQuote = market['quote'].toLowerCase (); const quoteVolume = 'vol_' + lowercaseQuote; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -70527,8 +68799,8 @@ module.exports = class foxbit extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -70541,14 +68813,11 @@ module.exports = class foxbit extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -70642,14 +68911,15 @@ module.exports = class foxbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],88:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],86:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending } = require ('./base/errors'); +const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending, ArgumentsRequired, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -70888,6 +69158,7 @@ module.exports = class ftx extends Exchange { 'An unexpected error occurred': ExchangeNotAvailable, // {"error":"An unexpected error occurred, please try again later (58BC21C795).","success":false} 'Please retry request': ExchangeNotAvailable, // {"error":"Please retry request","success":false} 'Please try again': ExchangeNotAvailable, // {"error":"Please try again","success":false} + 'Only have permissions for subaccount': PermissionDenied, // {"success":false,"error":"Only have permissions for subaccount *sub_name*"} }, }, 'precisionMode': TICK_SIZE, @@ -71011,8 +69282,8 @@ module.exports = class ftx extends Exchange { // check if a market is a spot or future market const symbol = (type === 'future') ? this.safeString (market, 'name') : (base + '/' + quote); const active = this.safeValue (market, 'enabled'); - const sizeIncrement = this.safeFloat (market, 'sizeIncrement'); - const priceIncrement = this.safeFloat (market, 'priceIncrement'); + const sizeIncrement = this.safeNumber (market, 'sizeIncrement'); + const priceIncrement = this.safeNumber (market, 'priceIncrement'); const precision = { 'amount': sizeIncrement, 'price': priceIncrement, @@ -71090,28 +69361,28 @@ module.exports = class ftx extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); const timestamp = this.safeTimestamp (ticker, 'time', this.milliseconds ()); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'change24h'), + 'percentage': this.safeNumber (ticker, 'change24h'), 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24h'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24h'), 'info': ticker, }; } @@ -71151,14 +69422,6 @@ module.exports = class ftx extends Exchange { return this.parseTicker (result, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetMarkets (params); @@ -71237,11 +69500,11 @@ module.exports = class ftx extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -71362,6 +69625,45 @@ module.exports = class ftx extends Exchange { // "type": "otc" // } // + // with -ve fee + // { + // "id": 1171258927, + // "fee": -0.0000713875, + // "side": "sell", + // "size": 1, + // "time": "2021-03-11T13:34:35.523627+00:00", + // "type": "order", + // "price": 14.2775, + // "future": null, + // "market": "SOL/USD", + // "feeRate": -0.000005, + // "orderId": 33182929044, + // "tradeId": 582936801, + // "liquidity": "maker", + // "feeCurrency": "USD", + // "baseCurrency": "SOL", + // "quoteCurrency": "USD" + // } + // + // // from OTC order + // { + // "id": 1172129651, + // "fee": 0, + // "side": "sell", + // "size": 1.47568846, + // "time": "2021-03-11T15:04:46.893383+00:00", + // "type": "otc", + // "price": 14.60932598, + // "future": null, + // "market": null, + // "feeRate": 0, + // "orderId": null, + // "tradeId": null, + // "liquidity": "taker", + // "feeCurrency": "USD", + // "baseCurrency": "BCHA", + // "quoteCurrency": "USD" + // } const id = this.safeString (trade, 'id'); const takerOrMaker = this.safeString (trade, 'liquidity'); const marketId = this.safeString (trade, 'market'); @@ -71379,25 +69681,24 @@ module.exports = class ftx extends Exchange { } } const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } const orderId = this.safeString (trade, 'orderId'); @@ -71503,8 +69804,8 @@ module.exports = class ftx extends Exchange { const result = this.safeValue (response, 'result', {}); return { 'info': response, - 'maker': this.safeFloat (result, 'makerFee'), - 'taker': this.safeFloat (result, 'takerFee'), + 'maker': this.safeNumber (result, 'makerFee'), + 'taker': this.safeNumber (result, 'takerFee'), }; } @@ -71531,11 +69832,11 @@ module.exports = class ftx extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'coin')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -71658,9 +69959,9 @@ module.exports = class ftx extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); let status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filledSize'); - let remaining = this.safeFloat (order, 'remainingSize'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filledSize'); + let remaining = this.safeNumber (order, 'remainingSize'); if ((remaining === 0.0) && (amount !== undefined) && (filled !== undefined)) { remaining = Math.max (amount - filled, 0); if (remaining > 0) { @@ -71684,15 +69985,15 @@ module.exports = class ftx extends Exchange { } const side = this.safeString (order, 'side'); const type = this.safeString (order, 'type'); - const average = this.safeFloat (order, 'avgFillPrice'); - const price = this.safeFloat2 (order, 'price', 'triggerPrice', average); + const average = this.safeNumber (order, 'avgFillPrice'); + const price = this.safeNumber2 (order, 'price', 'triggerPrice', average); let cost = undefined; if (filled !== undefined && price !== undefined) { cost = filled * price; } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'triggeredAt')); const clientOrderId = this.safeString (order, 'clientId'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -71738,22 +70039,28 @@ module.exports = class ftx extends Exchange { request['clientId'] = clientOrderId; params = this.omit (params, [ 'clientId', 'clientOrderId' ]); } - let priceToPrecision = undefined; - if (price !== undefined) { - priceToPrecision = parseFloat (this.priceToPrecision (symbol, price)); - } - let method = 'privatePostConditionalOrders'; + let method = undefined; if (type === 'limit') { method = 'privatePostOrders'; - request['price'] = priceToPrecision; + request['price'] = parseFloat (this.priceToPrecision (symbol, price)); } else if (type === 'market') { method = 'privatePostOrders'; request['price'] = null; } else if ((type === 'stop') || (type === 'takeProfit')) { - request['triggerPrice'] = priceToPrecision; - // request['orderPrice'] = number; // optional, order type is limit if this is specified, otherwise market + method = 'privatePostConditionalOrders'; + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerPrice'); + if (stopPrice === undefined) { + throw new ArgumentsRequired (this.id + ' createOrder () requires a stopPrice parameter or a triggerPrice parameter for ' + type + ' orders'); + } else { + params = this.omit (params, [ 'stopPrice', 'triggerPrice' ]); + request['triggerPrice'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + } + if (price !== undefined) { + request['orderPrice'] = parseFloat (this.priceToPrecision (symbol, price)); // optional, order type is limit if this is specified, otherwise market + } } else if (type === 'trailingStop') { - request['trailValue'] = priceToPrecision; // negative for "sell", positive for "buy" + method = 'privatePostConditionalOrders'; + request['trailValue'] = parseFloat (this.priceToPrecision (symbol, price)); // negative for "sell", positive for "buy" } else { throw new InvalidOrder (this.id + ' createOrder () does not support order type ' + type + ', only limit, market, stop, trailingStop, or takeProfit orders are supported'); } @@ -71819,9 +70126,9 @@ module.exports = class ftx extends Exchange { const request = {}; let method = undefined; const clientOrderId = this.safeString2 (params, 'client_order_id', 'clientOrderId'); - const triggerPrice = this.safeFloat (params, 'triggerPrice'); - const orderPrice = this.safeFloat (params, 'orderPrice'); - const trailValue = this.safeFloat (params, 'trailValue'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); + const orderPrice = this.safeNumber (params, 'orderPrice'); + const trailValue = this.safeNumber (params, 'trailValue'); params = this.omit (params, [ 'client_order_id', 'clientOrderId', 'triggerPrice', 'orderPrice', 'trailValue' ]); const triggerPriceIsDefined = (triggerPrice !== undefined); const orderPriceIsDefined = (orderPrice !== undefined); @@ -72184,7 +70491,7 @@ module.exports = class ftx extends Exchange { return this.parseTransaction (result, currency); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetAccount (params); // @@ -72317,7 +70624,7 @@ module.exports = class ftx extends Exchange { // const code = this.safeCurrencyCode (this.safeString (transaction, 'coin')); const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'size'); + const amount = this.safeNumber (transaction, 'size'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const txid = this.safeString (transaction, 'txid'); @@ -72334,7 +70641,7 @@ module.exports = class ftx extends Exchange { address = notes.slice (12); } } - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -72469,13 +70776,14 @@ module.exports = class ftx extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],89:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],87:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, ArgumentsRequired, InvalidAddress, OrderNotFound, NotSupported, DDoSProtection, InsufficientFunds, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -72636,9 +70944,12 @@ module.exports = class gateio extends Exchange { }, }, 'commonCurrencies': { + '88MPH': 'MPH', + 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', + 'MPH': 'Morpher', // conflict with 88MPH 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', }, @@ -72685,9 +70996,9 @@ module.exports = class gateio extends Exchange { const currency = coin[id]; const code = this.safeCurrencyCode (id); const delisted = this.safeValue (currency, 'delisted', 0); - const withdrawDisabled = this.safeValue (currency, 'withdraw_disabled', 0); - const depositDisabled = this.safeValue (currency, 'deposit_disabled', 0); - const tradeDisabled = this.safeValue (currency, 'trade_disabled', 0); + const withdrawDisabled = this.safeInteger2 (currency, 'withdraw_disabled', 0); + const depositDisabled = this.safeInteger2 (currency, 'deposit_disabled', 0); + const tradeDisabled = this.safeInteger2 (currency, 'trade_disabled', 0); const listed = (delisted === 0); const withdrawEnabled = (withdrawDisabled === 0); const depositEnabled = (depositDisabled === 0); @@ -72776,7 +71087,7 @@ module.exports = class gateio extends Exchange { 'price': this.safeInteger (details, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (details, 'min_amount'), + 'min': this.safeNumber (details, 'min_amount'), 'max': undefined, }; const priceLimits = { @@ -72784,7 +71095,7 @@ module.exports = class gateio extends Exchange { 'max': undefined, }; const defaultCost = amountLimits['min'] * priceLimits['min']; - const minCost = this.safeFloat (this.options['limits']['cost']['min'], quote, defaultCost); + const minCost = this.safeNumber (this.options['limits']['cost']['min'], quote, defaultCost); const costLimits = { 'min': minCost, 'max': undefined, @@ -72794,10 +71105,10 @@ module.exports = class gateio extends Exchange { 'price': priceLimits, 'cost': costLimits, }; - const disabled = this.safeValue (details, 'trade_disabled'); + const disabled = this.safeInteger (details, 'trade_disabled'); const active = !disabled; const uppercaseId = id.toUpperCase (); - const fee = this.safeFloat (details, 'fee'); + const fee = this.safeNumber (details, 'fee'); result.push ({ 'id': id, 'uppercaseId': uppercaseId, @@ -72831,11 +71142,11 @@ module.exports = class gateio extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (available, currencyId); - account['used'] = this.safeFloat (locked, currencyId); + account['free'] = this.safeString (available, currencyId); + account['used'] = this.safeString (locked, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -72851,11 +71162,11 @@ module.exports = class gateio extends Exchange { // they return [ Timestamp, Volume, Close, High, Low, Open ] return [ this.safeInteger (ohlcv, 0), // t - this.safeFloat (ohlcv, 5), // o - this.safeFloat (ohlcv, 3), // h - this.safeFloat (ohlcv, 4), // l - this.safeFloat (ohlcv, 2), // c - this.safeFloat (ohlcv, 1), // v + this.safeNumber (ohlcv, 5), // o + this.safeNumber (ohlcv, 3), // h + this.safeNumber (ohlcv, 4), // l + this.safeNumber (ohlcv, 2), // c + this.safeNumber (ohlcv, 1), // v ]; } @@ -72867,11 +71178,11 @@ module.exports = class gateio extends Exchange { 'group_sec': this.timeframes[timeframe], }; // max limit = 1001 - if (limit !== undefined) { - const periodDurationInSeconds = this.parseTimeframe (timeframe); - const hours = parseInt ((periodDurationInSeconds * limit) / 3600); - request['range_hour'] = Math.max (0, hours - 1); - } + // if (limit !== undefined) { + // const periodDurationInSeconds = this.parseTimeframe (timeframe); + // const hours = parseInt ((periodDurationInSeconds * limit) / 3600); + // request['range_hour'] = Math.max (1, hours - 1); + // } const response = await this.publicGetCandlestick2Id (this.extend (request, params)); // // { @@ -72895,8 +71206,8 @@ module.exports = class gateio extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'percentChange'); let open = undefined; let change = undefined; let average = undefined; @@ -72906,17 +71217,17 @@ module.exports = class gateio extends Exchange { change = last - open; average = this.sum (last, open) / 2; } - open = this.safeFloat (ticker, 'open', open); - change = this.safeFloat (ticker, 'change', change); + open = this.safeNumber (ticker, 'open', open); + change = this.safeNumber (ticker, 'change', change); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high24hr', 'high'), - 'low': this.safeFloat2 (ticker, 'low24hr', 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber2 (ticker, 'high24hr', 'high'), + 'low': this.safeNumber2 (ticker, 'low24hr', 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -72926,8 +71237,8 @@ module.exports = class gateio extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), // gateio has them reversed - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), // gateio has them reversed + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -72973,27 +71284,24 @@ module.exports = class gateio extends Exchange { const id = this.safeString2 (trade, 'tradeID', 'id'); // take either of orderid or orderId const orderId = this.safeString2 (trade, 'orderid', 'orderNumber'); - const price = this.safeFloat2 (trade, 'rate', 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString2 (trade, 'rate', 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'role'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } let fee = undefined; let feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee_coin')); - let feeCost = this.safeFloat (trade, 'point_fee'); + let feeCost = this.safeNumber (trade, 'point_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'gt_fee'); + feeCost = this.safeNumber (trade, 'gt_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'fee'); + feeCost = this.safeNumber (trade, 'fee'); } else { feeCurrency = this.safeCurrencyCode ('GT'); } @@ -73137,23 +71445,20 @@ module.exports = class gateio extends Exchange { } else if (side === '2') { side = 'buy'; } - const price = this.safeFloat2 (order, 'initialRate', 'rate'); - const average = this.safeFloat (order, 'filledRate'); - const amount = this.safeFloat2 (order, 'initialAmount', 'amount'); - const filled = this.safeFloat (order, 'filledAmount'); + const price = this.safeNumber2 (order, 'initialRate', 'rate'); + const average = this.safeNumber (order, 'filledRate'); + const amount = this.safeNumber2 (order, 'initialAmount', 'amount'); + const filled = this.safeNumber (order, 'filledAmount'); // In the order status response, this field has a different name. - let remaining = this.safeFloat2 (order, 'leftAmount', 'left'); - if (remaining === undefined) { - remaining = amount - filled; - } - const feeCost = this.safeFloat (order, 'feeValue'); + const remaining = this.safeNumber2 (order, 'leftAmount', 'left'); + const feeCost = this.safeNumber (order, 'feeValue'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (order, 'feePercentage'); + let feeRate = this.safeNumber (order, 'feePercentage'); if (feeRate !== undefined) { feeRate = feeRate / 100; } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -73179,7 +71484,7 @@ module.exports = class gateio extends Exchange { 'rate': feeRate, }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -73370,7 +71675,7 @@ module.exports = class gateio extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'txid'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); if (address === 'false') { address = undefined; @@ -73378,7 +71683,7 @@ module.exports = class gateio extends Exchange { const timestamp = this.safeTimestamp (transaction, 'timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.parseTransactionType (id[0]); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -73467,7 +71772,7 @@ module.exports = class gateio extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],90:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],88:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -73475,6 +71780,7 @@ module.exports = class gateio extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidOrder, InvalidNonce, InsufficientFunds, AuthenticationError, PermissionDenied, NotSupported, OnMaintenance, RateLimitExceeded, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -73691,16 +71997,16 @@ module.exports = class gemini extends Exchange { // const base = this.safeCurrencyCode (baseId); const minAmountString = cells[1].replace ('', ''); const minAmountParts = minAmountString.split (' '); - const minAmount = this.safeFloat (minAmountParts, 0); + const minAmount = this.safeNumber (minAmountParts, 0); const amountPrecisionString = cells[2].replace ('', ''); const amountPrecisionParts = amountPrecisionString.split (' '); - const amountPrecision = this.safeFloat (amountPrecisionParts, 0); + const amountPrecision = this.safeNumber (amountPrecisionParts, 0); const idLength = marketId.length - 0; const quoteId = marketId.slice (idLength - 3, idLength); const quote = this.safeCurrencyCode (quoteId); const pricePrecisionString = cells[3].replace ('', ''); const pricePrecisionParts = pricePrecisionString.split (' '); - const pricePrecision = this.safeFloat (pricePrecisionParts, 0); + const pricePrecision = this.safeNumber (pricePrecisionParts, 0); const baseId = marketId.replace (quoteId, ''); const base = this.safeCurrencyCode (baseId); const symbol = base + '/' + quote; @@ -73928,11 +72234,11 @@ module.exports = class gemini extends Exchange { base = market['base']; quote = market['quote']; } - const price = this.safeFloat (ticker, 'price'); - const last = this.safeFloat2 (ticker, 'last', 'close', price); - let percentage = this.safeFloat (ticker, 'percentChange24h'); + const price = this.safeNumber (ticker, 'price'); + const last = this.safeNumber2 (ticker, 'last', 'close', price); + let percentage = this.safeNumber (ticker, 'percentChange24h'); let change = undefined; - let open = this.safeFloat (ticker, 'open'); + let open = this.safeNumber (ticker, 'open'); let average = undefined; if (last !== undefined) { if (open !== undefined) { @@ -73949,18 +72255,18 @@ module.exports = class gemini extends Exchange { average = this.sum (last, open) / 2; } } - const baseVolume = this.safeFloat (volume, baseId); - const quoteVolume = this.safeFloat (volume, quoteId); + const baseVolume = this.safeNumber (volume, baseId); + const quoteVolume = this.safeNumber (volume, quoteId); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -73976,14 +72282,6 @@ module.exports = class gemini extends Exchange { }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetV1Pricefeed (params); @@ -74024,17 +72322,14 @@ module.exports = class gemini extends Exchange { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); const fee = { - 'cost': this.safeFloat (trade, 'fee_amount'), + 'cost': this.safeNumber (trade, 'fee_amount'), 'currency': feeCurrencyCode, }; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeStringLower (trade, 'type'); const symbol = this.safeSymbol (undefined, market); @@ -74087,18 +72382,18 @@ module.exports = class gemini extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'timestampms'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const filled = this.safeFloat (order, 'executed_amount'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const filled = this.safeNumber (order, 'executed_amount'); let status = 'closed'; if (order['is_live']) { status = 'open'; @@ -74106,14 +72401,8 @@ module.exports = class gemini extends Exchange { if (order['is_cancelled']) { status = 'canceled'; } - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_execution_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_execution_price'); let type = this.safeString (order, 'type'); if (type === 'exchange limit') { type = 'limit'; @@ -74128,7 +72417,7 @@ module.exports = class gemini extends Exchange { const id = this.safeString (order, 'order_id'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'client_order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -74144,13 +72433,13 @@ module.exports = class gemini extends Exchange { 'price': price, 'stopPrice': undefined, 'average': average, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -74265,7 +72554,7 @@ module.exports = class gemini extends Exchange { status = 'ok'; } let fee = undefined; - const feeAmount = this.safeFloat (transaction, 'feeAmount'); + const feeAmount = this.safeNumber (transaction, 'feeAmount'); if (feeAmount !== undefined) { fee = { 'cost': feeAmount, @@ -74281,7 +72570,7 @@ module.exports = class gemini extends Exchange { 'address': address, 'tag': undefined, // or is it defined? 'type': type, // direction of the transaction, ('deposit' | 'withdraw') - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': undefined, @@ -74380,7 +72669,7 @@ module.exports = class gemini extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],91:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],89:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -74388,6 +72677,7 @@ module.exports = class gemini extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors'); const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -74601,8 +72891,8 @@ module.exports = class gopax extends Exchange { const minimums = this.safeValue (market, 'restApiOrderAmountMin', {}); const marketAsk = this.safeValue (minimums, 'marketAsk', {}); const marketBid = this.safeValue (minimums, 'marketBid', {}); - const takerFeePercent = this.safeFloat (market, 'takerFeePercent'); - const makerFeePercent = this.safeFloat (market, 'makerFeePercent'); + const takerFeePercent = this.safeNumber (market, 'takerFeePercent'); + const makerFeePercent = this.safeNumber (market, 'makerFeePercent'); const taker = parseFloat (this.decimalToPrecision (takerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); const maker = parseFloat (this.decimalToPrecision (makerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); result.push ({ @@ -74620,15 +72910,15 @@ module.exports = class gopax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (marketAsk, 'amount'), + 'min': this.safeNumber (marketAsk, 'amount'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'priceMin'), + 'min': this.safeNumber (market, 'priceMin'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (marketBid, 'amount'), + 'min': this.safeNumber (marketBid, 'amount'), 'max': undefined, }, }, @@ -74663,8 +72953,8 @@ module.exports = class gopax extends Exchange { const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'name'); - const fee = this.safeFloat (currency, 'withdrawalFee'); - const precision = this.safeFloat (currency, 'scale'); + const fee = this.safeNumber (currency, 'withdrawalFee'); + const precision = this.safeNumber (currency, 'scale'); result[code] = { 'id': id, 'info': currency, @@ -74687,7 +72977,7 @@ module.exports = class gopax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalAmountMin'), + 'min': this.safeNumber (currency, 'withdrawalAmountMin'), 'max': undefined, }, }, @@ -74755,8 +73045,8 @@ module.exports = class gopax extends Exchange { const marketId = this.safeString (ticker, 'name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (ticker, 'time')); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat2 (ticker, 'price', 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'price', 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -74767,20 +73057,20 @@ module.exports = class gopax extends Exchange { percentage = change / open * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidVolume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askVolume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidVolume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askVolume'), 'vwap': vwap, 'open': open, 'close': last, @@ -74816,14 +73106,6 @@ module.exports = class gopax extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTradingPairsStats (params); @@ -74845,8 +73127,8 @@ module.exports = class gopax extends Exchange { parsePublicTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let symbol = undefined; if ('symbol' in market) { symbol = this.safeString (market, 'symbol'); @@ -74872,14 +73154,14 @@ module.exports = class gopax extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const symbol = this.safeString (trade, 'tradingPairName').replace ('-', '/'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'baseAmount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'baseAmount'); let feeCurrency = symbol.slice (0, 3); if (side === 'sell') { feeCurrency = symbol.slice (4); } const fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': feeCurrency, 'rate': undefined, }; @@ -74961,15 +73243,15 @@ module.exports = class gopax extends Exchange { } else if (type === '2') { type = 'market'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'baseAmount'); - let cost = this.safeFloat (trade, 'quoteAmount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'baseAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteAmount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -75036,11 +73318,11 @@ module.exports = class gopax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -75080,14 +73362,14 @@ module.exports = class gopax extends Exchange { const balance = response[i]; const currencyId = this.safeString2 (balance, 'asset', 'isoAlpha3'); const code = this.safeCurrencyCode (currencyId); - const hold = this.safeFloat (balance, 'hold'); - const pendingWithdrawal = this.safeFloat (balance, 'pendingWithdrawal'); + const hold = this.safeString (balance, 'hold'); + const pendingWithdrawal = this.safeString (balance, 'pendingWithdrawal'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.sum (hold, pendingWithdrawal); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = Precise.stringAdd (hold, pendingWithdrawal); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -75164,42 +73446,36 @@ module.exports = class gopax extends Exchange { const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); const timeInForce = this.safeStringUpper (order, 'timeInForce'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - const remaining = this.safeFloat (order, 'remaining'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const stopPrice = this.safeNumber (order, 'stopPrice'); + const remaining = this.safeNumber (order, 'remaining'); const marketId = this.safeString (order, 'tradingPairName'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const balanceChange = this.safeValue (order, 'balanceChange', {}); - let filled = this.safeFloat (balanceChange, 'baseNet'); - let cost = this.safeFloat (balanceChange, 'quoteNet'); + const filled = this.safeNumber (balanceChange, 'baseNet'); + let cost = this.safeNumber (balanceChange, 'quoteNet'); if (cost !== undefined) { cost = Math.abs (cost); } let updated = undefined; - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } if ((filled !== undefined) && (filled > 0)) { updated = this.parse8601 (this.safeString (order, 'updatedAt')); } - if ((cost === undefined) && (price !== undefined) && (filled !== undefined)) { - cost = filled * price; - } let fee = undefined; if (side === 'buy') { const baseFee = this.safeValue (balanceChange, 'baseFee', {}); - const taking = this.safeFloat (baseFee, 'taking'); - const making = this.safeFloat (baseFee, 'making'); + const taking = this.safeNumber (baseFee, 'taking'); + const making = this.safeNumber (baseFee, 'making'); fee = { 'currency': market['base'], 'cost': this.sum (taking, making), }; } else { const quoteFee = this.safeValue (balanceChange, 'quoteFee', {}); - const taking = this.safeFloat (quoteFee, 'taking'); - const making = this.safeFloat (quoteFee, 'making'); + const taking = this.safeNumber (quoteFee, 'taking'); + const making = this.safeNumber (quoteFee, 'making'); fee = { 'currency': market['quote'], 'cost': this.sum (taking, making), @@ -75209,7 +73485,7 @@ module.exports = class gopax extends Exchange { if (timeInForce !== undefined) { postOnly = (timeInForce === 'PO'); } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'datetime': this.iso8601 (timestamp), @@ -75231,7 +73507,7 @@ module.exports = class gopax extends Exchange { 'trades': undefined, 'fee': fee, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -75379,7 +73655,7 @@ module.exports = class gopax extends Exchange { request['clientOrderId'] = clientOrderId; params = this.omit (params, 'clientOrderId'); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -75508,18 +73784,6 @@ module.exports = class gopax extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetCryptoDepositAddresses (params); @@ -75584,8 +73848,8 @@ module.exports = class gopax extends Exchange { } else if ((type === 'crypto_deposit' || type === 'fiat_deposit')) { type = 'deposit'; } - const amount = this.safeFloat (transaction, 'netAmount'); - const feeCost = this.safeFloat (transaction, 'feeAmount'); + const amount = this.safeNumber (transaction, 'netAmount'); + const feeCost = this.safeNumber (transaction, 'feeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -75729,7 +73993,7 @@ module.exports = class gopax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],92:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],90:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -75737,6 +74001,7 @@ module.exports = class gopax extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -76036,23 +74301,23 @@ module.exports = class hbtc extends Exchange { const filter = filters[j]; const filterType = this.safeString (filter, 'filterType'); if (filterType === 'LOT_SIZE') { - amountMin = this.safeFloat (filter, 'minQty'); - amountMax = this.safeFloat (filter, 'maxQty'); + amountMin = this.safeNumber (filter, 'minQty'); + amountMax = this.safeNumber (filter, 'maxQty'); } if (filterType === 'PRICE_FILTER') { - priceMin = this.safeFloat (filter, 'minPrice'); - priceMax = this.safeFloat (filter, 'maxPrice'); + priceMin = this.safeNumber (filter, 'minPrice'); + priceMax = this.safeNumber (filter, 'maxPrice'); } if (filterType === 'MIN_NOTIONAL') { - costMin = this.safeFloat (filter, 'minNotional'); + costMin = this.safeNumber (filter, 'minNotional'); } } if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) { costMin = amountMin * priceMin; } const precision = { - 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'), - 'amount': this.safeFloat (market, 'baseAssetPrecision'), + 'price': this.safeNumber2 (market, 'quotePrecision', 'quoteAssetPrecision'), + 'amount': this.safeNumber (market, 'baseAssetPrecision'), }; const limits = { 'amount': { @@ -76290,14 +74555,6 @@ module.exports = class hbtc extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidAsk (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -76449,8 +74706,8 @@ module.exports = class hbtc extends Exchange { const currencyId = this.safeString2 (balance, 'asset', 'tokenName'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -76460,12 +74717,12 @@ module.exports = class hbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = response[currencyId]; const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableMargin'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'availableMargin'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTrades (symbol, since = undefined, limit = 50, params = {}) { @@ -76506,11 +74763,11 @@ module.exports = class hbtc extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -77196,8 +75453,8 @@ module.exports = class hbtc extends Exchange { // const currencyId = this.safeString (item, 'tokenId'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'change'); - const after = this.safeFloat (item, 'total'); + const amount = this.safeNumber (item, 'change'); + const after = this.safeNumber (item, 'total'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -77337,8 +75594,8 @@ module.exports = class hbtc extends Exchange { } else { type = 'withdrawal'; } - const amount = this.safeFloat (transaction, 'quantity'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'quantity'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'feeTokenId'); @@ -77399,8 +75656,8 @@ module.exports = class hbtc extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'openPrice'); - const close = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; let average = undefined; @@ -77411,19 +75668,19 @@ module.exports = class hbtc extends Exchange { percentage = (change / open) * 100; } } - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber2 (ticker, 'bestBidPrice', 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber2 (ticker, 'bestAskPrice', 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': vwap, 'open': open, 'close': close, @@ -77473,17 +75730,14 @@ module.exports = class hbtc extends Exchange { // } // const id = this.safeString (trade, 'id'); - const timestamp = this.safeFloat (trade, 'time'); + const timestamp = this.safeNumber (trade, 'time'); const type = undefined; const orderId = this.safeString (trade, 'orderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let side = undefined; let takerOrMaker = undefined; if ('isBuyerMaker' in trade) { @@ -77497,7 +75751,7 @@ module.exports = class hbtc extends Exchange { side = isBuyer ? 'buy' : 'sell'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -77603,30 +75857,30 @@ module.exports = class hbtc extends Exchange { const symbol = this.safeSymbol (marketId, market); let type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'avgPrice'); + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'avgPrice'); let amount = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); + let cost = this.safeNumber (order, 'cummulativeQuoteQty'); let filled = undefined; let remaining = undefined; if (type === undefined) { type = this.safeStringLower (order, 'orderType'); if ((market !== undefined) && market['inverse']) { - cost = this.safeFloat (order, 'executedQty'); + cost = this.safeNumber (order, 'executedQty'); amount = undefined; } if (cost === 0.0) { filled = 0; } } else { - amount = this.safeFloat (order, 'origQty'); + amount = this.safeNumber (order, 'origQty'); if (type === 'market') { price = undefined; if (side === 'buy') { amount = undefined; } } - filled = this.safeFloat (order, 'executedQty'); + filled = this.safeNumber (order, 'executedQty'); if (filled !== undefined) { if (amount !== undefined) { remaining = amount - filled; @@ -77638,7 +75892,7 @@ module.exports = class hbtc extends Exchange { } const status = this.parseOrderStatus (this.safeString (order, 'status')); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const result = { 'info': order, 'id': id, @@ -77667,7 +75921,7 @@ module.exports = class hbtc extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'fee'); + const feeCost = this.safeNumber (fees[i], 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'feeToken'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -77740,7 +75994,7 @@ module.exports = class hbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],93:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],91:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -77748,6 +76002,7 @@ module.exports = class hbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, PermissionDenied, ExchangeError, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, RequestTimeout, AuthenticationError } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -77787,6 +76042,7 @@ module.exports = class hitbtc extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': 'M1', @@ -77824,10 +76080,10 @@ module.exports = class hitbtc extends Exchange { 'api': { 'public': { 'get': [ - 'symbol', // Available Currency Symbols - 'symbol/{symbol}', // Get symbol info 'currency', // Available Currencies 'currency/{currency}', // Get currency info + 'symbol', // Available Currency Symbols + 'symbol/{symbol}', // Get symbol info 'ticker', // Ticker list for all symbols 'ticker/{symbol}', // Ticker for symbol 'trades', @@ -77845,11 +76101,20 @@ module.exports = class hitbtc extends Exchange { 'order/{clientOrderId}', // Get a single order by clientOrderId 'trading/fee/all', // Get trading fee rate 'trading/fee/{symbol}', // Get trading fee rate + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', 'history/order', // Get historical orders 'history/trades', // Get historical trades 'history/order/{orderId}/trades', // Get historical trades by specified order 'account/balance', // Get main acccount balance - 'account/crypto/address/{currency}', // Get deposit crypro address + 'account/crypto/address/{currency}', // Get current address + 'account/crypto/addresses/{currency}', // Get last 10 deposit addresses for currency + 'account/crypto/used-addresses/{currency}', // Get last 10 unique addresses used for withdraw by currency + 'account/crypto/estimate-withdraw', 'account/crypto/is-mine/{address}', 'account/transactions', // Get account transactions 'account/transactions/{id}', // Get account transaction by id @@ -77860,23 +76125,33 @@ module.exports = class hitbtc extends Exchange { ], 'post': [ 'order', // Create new order - 'account/crypto/address/{currency}', // Create new deposit crypro address - 'account/crypto/withdraw', // Withdraw crypro + 'margin/order', + 'account/crypto/address/{currency}', // Create new crypto deposit address + 'account/crypto/withdraw', // Withdraw crypto 'account/crypto/transfer-convert', - 'account/transfer', // Transfer amount to trading + 'account/transfer', // Transfer amount to trading account or to main account + 'account/transfer/internal', 'sub-acc/freeze', 'sub-acc/activate', 'sub-acc/transfer', ], 'put': [ 'order/{clientOrderId}', // Create new order - 'account/crypto/withdraw/{id}', // Commit withdraw crypro + 'margin/account/{symbol}', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Commit crypto withdrawal 'sub-acc/acl/{subAccountUserId}', ], 'delete': [ 'order', // Cancel all open orders 'order/{clientOrderId}', // Cancel order - 'account/crypto/withdraw/{id}', // Rollback withdraw crypro + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Rollback crypto withdrawal ], // outdated? 'patch': [ @@ -77895,8 +76170,20 @@ module.exports = class hitbtc extends Exchange { }, 'options': { 'defaultTimeInForce': 'FOK', + 'accountsByType': { + 'bank': 'bank', + 'exchange': 'exchange', + 'main': 'bank', // alias of the above + 'trading': 'exchange', + }, + 'fetchBalanceMethod': { + 'account': 'account', + 'main': 'account', + 'trading': 'trading', + }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive 'BET': 'DAO.Casino', 'BOX': 'BOX Token', @@ -77923,7 +76210,6 @@ module.exports = class hitbtc extends Exchange { '20002': OrderNotFound, // canceling non-existent order '20001': InsufficientFunds, // {"error":{"code":20001,"message":"Insufficient funds","description":"Check that the funds are sufficient, given commissions"}} }, - 'orders': {}, // orders cache / emulation }); } @@ -77960,14 +76246,14 @@ module.exports = class hitbtc extends Exchange { if (id.indexOf ('_') >= 0) { symbol = id; } - const lot = this.safeFloat (market, 'quantityIncrement'); - const step = this.safeFloat (market, 'tickSize'); + const lot = this.safeNumber (market, 'quantityIncrement'); + const step = this.safeNumber (market, 'tickSize'); const precision = { 'price': step, 'amount': lot, }; - const taker = this.safeFloat (market, 'takeLiquidityRate'); - const maker = this.safeFloat (market, 'provideLiquidityRate'); + const taker = this.safeNumber (market, 'takeLiquidityRate'); + const maker = this.safeNumber (market, 'provideLiquidityRate'); const feeCurrencyId = this.safeString (market, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); result.push (this.extend (this.fees['trading'], { @@ -78002,6 +76288,49 @@ module.exports = class hitbtc extends Exchange { return result; } + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // account can be "exchange" or "bank", with aliases "main" or "trading" respectively + await this.loadMarkets (); + const currency = this.currency (code); + const requestAmount = this.currencyToPrecision (code, amount); + const request = { + 'currency': currency['id'], + 'amount': requestAmount, + }; + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + const keys = Object.keys (accountsByType); + if (fromId === undefined) { + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ') + ' instead of ' + fromId); + } + if (toId === undefined) { + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ') + ' instead of ' + toId); + } + if (fromId === toId) { + throw new ExchangeError (this.id + ' from and to cannot be the same account'); + } + type = fromId + 'To' + this.capitalize (toId); + } + request['type'] = type; + const response = await this.privatePostAccountTransfer (this.extend (request, params)); + // { id: '2db6ebab-fb26-4537-9ef8-1a689472d236' } + const id = this.safeString (response, 'id'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'amount': requestAmount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': undefined, + }; + } + async fetchCurrencies (params = {}) { const response = await this.publicGetCurrency (params); // @@ -78057,7 +76386,7 @@ module.exports = class hitbtc extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'payoutFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'payoutFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -78097,15 +76426,20 @@ module.exports = class hitbtc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } async fetchBalance (params = {}) { await this.loadMarkets (); const type = this.safeString (params, 'type', 'trading'); - const method = 'privateGet' + this.capitalize (type) + 'Balance'; + const fetchBalanceAccounts = this.safeValue (this.options, 'fetchBalanceMethod', {}); + const typeId = this.safeString (fetchBalanceAccounts, type); + if (typeId === undefined) { + throw new ExchangeError (this.id + ' fetchBalance account type must be either main or trading'); + } + const method = 'privateGet' + this.capitalize (typeId) + 'Balance'; const query = this.omit (params, 'type'); const response = await this[method] (query); const result = { 'info': response }; @@ -78114,11 +76448,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -78135,11 +76469,11 @@ module.exports = class hitbtc extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'max'), - this.safeFloat (ohlcv, 'min'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'max'), + this.safeNumber (ohlcv, 'min'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -78185,10 +76519,10 @@ module.exports = class hitbtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); let change = undefined; let percentage = undefined; let average = undefined; @@ -78204,11 +76538,11 @@ module.exports = class hitbtc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -78284,7 +76618,7 @@ module.exports = class hitbtc extends Exchange { market = this.safeMarket (marketId, market); const symbol = market['symbol']; let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = market ? market['feeCurrency'] : undefined; fee = { @@ -78296,9 +76630,11 @@ module.exports = class hitbtc extends Exchange { // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const orderId = this.safeString (trade, 'clientOrderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); const id = this.safeString (trade, 'id'); return { @@ -78397,11 +76733,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'hash'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -78589,66 +76925,25 @@ module.exports = class hitbtc extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'cumQuantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'cumQuantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); // we use clientOrderId as the order id with this exchange intentionally // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const id = this.safeString (order, 'clientOrderId'); const clientOrderId = id; - let price = this.safeFloat (order, 'price'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - if (price !== undefined) { - cost = filled * price; - } - } - } + const price = this.safeNumber (order, 'price'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); let trades = this.safeValue (order, 'tradesReport'); - let fee = undefined; - let average = this.safeValue (order, 'avgPrice'); + const fee = undefined; + const average = this.safeNumber (order, 'avgPrice'); if (trades !== undefined) { trades = this.parseTrades (trades, market); - let feeCost = undefined; - const numTrades = trades.length; - let tradesCost = 0; - for (let i = 0; i < numTrades; i++) { - if (feeCost === undefined) { - feeCost = 0; - } - tradesCost = this.sum (tradesCost, trades[i]['cost']); - const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); - if (tradeFeeCost !== undefined) { - feeCost = this.sum (feeCost, tradeFeeCost); - } - } - cost = tradesCost; - if ((filled !== undefined) && (filled > 0)) { - if (average === undefined) { - average = cost / filled; - } - if (type === 'market') { - if (price === undefined) { - price = average; - } - } - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, // https://github.com/ccxt/ccxt/issues/5674 'timestamp': created, @@ -78663,13 +76958,13 @@ module.exports = class hitbtc extends Exchange { 'stopPrice': undefined, 'average': average, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -78930,7 +77225,7 @@ module.exports = class hitbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],94:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],92:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -78938,6 +77233,7 @@ module.exports = class hitbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { BadRequest, AuthenticationError, NetworkError, ArgumentsRequired, OrderNotFound, InsufficientFunds } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -78948,7 +77244,7 @@ module.exports = class hollaex extends Exchange { 'name': 'HollaEx', 'countries': [ 'KR' ], 'rateLimit': 333, - 'version': 'v1', + 'version': 'v2', 'has': { 'CORS': false, 'fetchMarkets': true, @@ -78968,13 +77264,13 @@ module.exports = class hollaex extends Exchange { 'cancelOrder': true, 'cancelAllOrders': true, 'fetchOpenOrders': true, - 'fetchClosedOrders': false, + 'fetchClosedOrders': true, 'fetchOpenOrder': true, 'fetchOrder': false, 'fetchDeposits': true, 'fetchWithdrawals': true, 'fetchTransactions': false, - 'fetchOrders': false, + 'fetchOrders': true, 'fetchMyTrades': true, 'withdraw': true, 'fetchDepositAddress': true, @@ -78999,13 +77295,17 @@ module.exports = class hollaex extends Exchange { 'public': { 'get': [ 'health', - 'constant', + 'constants', + 'kit', + 'tiers', 'ticker', - 'ticker/all', + 'tickers', + 'orderbook', 'orderbooks', 'trades', 'chart', - // TradingView data + 'charts', + // TradingView 'udf/config', 'udf/history', 'udf/symbols', @@ -79015,20 +77315,20 @@ module.exports = class hollaex extends Exchange { 'get': [ 'user', 'user/balance', - 'user/trades', - 'user/orders', - 'user/orders/{order_id}', 'user/deposits', 'user/withdrawals', - 'user/withdraw/{currency}/fee', + 'user/withdrawal/fee', + 'user/trades', + 'orders', + 'orders/{order_id}', ], 'post': [ 'user/request-withdrawal', 'order', ], 'delete': [ - 'user/orders', - 'user/orders/{order_id}', + 'order/all', + 'order', ], }, }, @@ -79063,7 +77363,7 @@ module.exports = class hollaex extends Exchange { } async fetchMarkets (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); // // { // coins: { @@ -79130,17 +77430,17 @@ module.exports = class hollaex extends Exchange { 'quoteId': quoteId, 'active': active, 'precision': { - 'price': this.safeFloat (market, 'increment_price'), - 'amount': this.safeFloat (market, 'increment_size'), + 'price': this.safeNumber (market, 'increment_price'), + 'amount': this.safeNumber (market, 'increment_size'), }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, 'max': undefined }, }, @@ -79151,7 +77451,7 @@ module.exports = class hollaex extends Exchange { } async fetchCurrencies (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); const coins = this.safeValue (response, 'coins', {}); const keys = Object.keys (coins); const result = {}; @@ -79163,8 +77463,8 @@ module.exports = class hollaex extends Exchange { const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'fullname'); const active = this.safeValue (currency, 'active'); - const fee = this.safeFloat (currency, 'withdrawal_fee'); - const precision = this.safeFloat (currency, 'increment_unit'); + const fee = this.safeNumber (currency, 'withdrawal_fee'); + const precision = this.safeNumber (currency, 'increment_unit'); const withdrawalLimits = this.safeValue (currency, 'withdrawal_limits', []); result[code] = { 'id': id, @@ -79177,8 +77477,8 @@ module.exports = class hollaex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min'), - 'max': this.safeFloat (currency, 'max'), + 'min': this.safeNumber (currency, 'min'), + 'max': this.safeNumber (currency, 'max'), }, 'price': { 'min': undefined, @@ -79267,7 +77567,7 @@ module.exports = class hollaex extends Exchange { async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.publicGetTickerAll (this.extend (params)); + const response = await this.publicGetTickers (this.extend (params)); // // { // "bch-usdt": { @@ -79330,27 +77630,27 @@ module.exports = class hollaex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString2 (ticker, 'time', 'timestamp')); - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const result = { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, - 'last': this.safeFloat (ticker, 'last', close), + 'last': this.safeNumber (ticker, 'last', close), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, }; return result; @@ -79408,15 +77708,12 @@ module.exports = class hollaex extends Exchange { const datetime = this.safeString (trade, 'timestamp'); const timestamp = this.parse8601 (datetime); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const quote = market['quote']; @@ -79501,11 +77798,11 @@ module.exports = class hollaex extends Exchange { // return [ this.parse8601 (this.safeString (response, 'time')), - this.safeFloat (response, 'open'), - this.safeFloat (response, 'high'), - this.safeFloat (response, 'low'), - this.safeFloat (response, 'close'), - this.safeFloat (response, 'volume'), + this.safeNumber (response, 'open'), + this.safeNumber (response, 'high'), + this.safeNumber (response, 'low'), + this.safeNumber (response, 'close'), + this.safeNumber (response, 'volume'), ]; } @@ -79530,11 +77827,11 @@ module.exports = class hollaex extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (response, currencyId + '_available'); - account['total'] = this.safeFloat (response, currencyId + '_balance'); + account['free'] = this.safeString (response, currencyId + '_available'); + account['total'] = this.safeString (response, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrder (id, symbol = undefined, params = {}) { @@ -79542,67 +77839,146 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateGetUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateGetOrdersOrderId (this.extend (request, params)); // // { - // "created_at": "2018-03-23T04:14:08.663Z", - // "title": "string", - // "side": "sell", - // "type": "limit", - // "price": 0, - // "size": 0, - // "symbol": "xht-usdt", // "id": "string", - // "created_by": 1, - // "filled": 0 + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } // } // return this.parseOrder (response); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'open': true, + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'status': 'filled', + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = undefined; - const request = {}; + const request = { + // 'symbol': market['id'], + // 'side': 'buy', // 'sell' + // 'status': 'new', // 'filled', 'pfilled', 'canceled' + // 'open': true, + // 'limit': limit, // default 50, max 100 + // 'page': 1, + // 'order_by': 'created_at', // id, ... + // 'order': 'asc', // 'desc' + // 'start_date': this.iso8601 (since), + // 'end_date': this.iso8601 (this.milliseconds ()), + }; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } - const response = await this.privateGetUserOrders (this.extend (request, params)); + if (since !== undefined) { + request['start_date'] = this.iso8601 (since); + } + if (limit !== undefined) { + request['limit'] = limit; // default 50, max 100 + } + const response = await this.privateGetOrders (this.extend (request, params)); // - // [ - // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 - // } - // ] + // { + // "count": 1, + // "data": [ + // { + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } + // } + // ] + // } // - return this.parseOrders (response, market); + const data = this.safeValue (response, 'data', []); + return this.parseOrders (data, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'new': 'open', + 'pfilled': 'open', + 'filled': 'closed', + 'canceled': 'canceled', + }; + return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // - // fetchOpenOrder, fetchOpenOrders + // createOrder, fetchOpenOrder, fetchOpenOrders // // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // }, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, // } // const marketId = this.safeString (order, 'symbol'); @@ -79611,21 +77987,11 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filled'); - let cost = undefined; - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = filled * price; - } - } - const status = (type === 'market') ? 'closed' : 'open'; - const result = { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filled'); + const status = this.parseOrderStatus (this.safeString (order, 'status')); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -79641,40 +78007,56 @@ module.exports = class hollaex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; - return result; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); - const order = { + const request = { 'symbol': market['id'], 'side': side, 'size': amount, 'type': type, + // 'stop': parseFloat (this.priceToPrecision (symbol, stopPrice)), + // 'meta': {}, // other options such as post_only }; if (type !== 'market') { - order['price'] = price; + request['price'] = price; } - const response = await this.privatePostOrder (this.extend (order, params)); + const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop'); + if (stopPrice !== undefined) { + request['stop'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + params = this.omit (params, [ 'stopPrice', 'stop' ]); + } + const response = await this.privatePostOrder (this.extend (request, params)); // // { + // "fee": 0, + // "meta": {}, // "symbol": "xht-usdt", // "side": "sell", - // "size": 1, + // "size": 0.1, // "type": "limit", - // "price": 0.1, + // "price": 1, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, + // "fee_coin": "usdt", // "id": "string", - // "created_by": 34, + // "created_by": 116, // "filled": 0, - // "status": "pending" + // "status": "new", + // "updated_at": "2021-02-17T03:03:19.231Z", + // "created_at": "2021-02-17T03:03:19.231Z", + // "stop": null // } // return this.parseOrder (response, market); @@ -79685,7 +78067,7 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateDeleteUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateDeleteOrder (this.extend (request, params)); // // { // "title": "string", @@ -79710,7 +78092,7 @@ module.exports = class hollaex extends Exchange { market = this.markets (symbol); request['symbol'] = market['id']; } - const response = await this.privateDeleteUserOrders (this.extend (request, params)); + const response = await this.privateDeleteOrderAll (this.extend (request, params)); // // [ // { @@ -79976,7 +78358,7 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_at')); const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const type = this.safeString (transaction, 'type'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); let addressTo = undefined; const addressFrom = undefined; @@ -80006,7 +78388,7 @@ module.exports = class hollaex extends Exchange { } const fee = { 'currency': code, - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), }; return { 'info': transaction, @@ -80105,7 +78487,7 @@ module.exports = class hollaex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],95:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],93:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -80146,7 +78528,7 @@ module.exports = class huobijp extends huobipro { } }; -},{"./base/errors":8,"./huobipro.js":96}],96:[function(require,module,exports){ +},{"./base/errors":9,"./huobipro.js":94}],94:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -80154,6 +78536,7 @@ module.exports = class huobijp extends huobipro { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, ExchangeNotAvailable, OnMaintenance, InvalidOrder, OrderNotFound, InsufficientFunds, ArgumentsRequired, BadSymbol, BadRequest, RequestTimeout, NetworkError } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -80171,7 +78554,9 @@ module.exports = class huobipro extends Exchange { 'hostname': 'api.huobi.pro', // api.testnet.huobi.pro 'pro': true, 'has': { + 'cancelAllOrders': true, 'cancelOrder': true, + 'cancelOrders': true, 'CORS': false, 'createOrder': true, 'fetchBalance': true, @@ -80338,6 +78723,7 @@ module.exports = class huobipro extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.002, @@ -80401,6 +78787,7 @@ module.exports = class huobipro extends Exchange { // https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/ 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', + 'BIFI': 'Bitcoin File', // conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706 }, }); } @@ -80465,8 +78852,8 @@ module.exports = class huobipro extends Exchange { 'info': limits, 'limits': { 'amount': { - 'min': this.safeFloat (limits, 'limit-order-must-greater-than'), - 'max': this.safeFloat (limits, 'limit-order-must-less-than'), + 'min': this.safeNumber (limits, 'limit-order-must-greater-than'), + 'max': this.safeNumber (limits, 'limit-order-must-less-than'), }, }, }; @@ -80500,9 +78887,9 @@ module.exports = class huobipro extends Exchange { }; const maker = (base === 'OMG') ? 0 : 0.2 / 100; const taker = (base === 'OMG') ? 0 : 0.2 / 100; - const minAmount = this.safeFloat (market, 'min-order-amt', Math.pow (10, -precision['amount'])); - const maxAmount = this.safeFloat (market, 'max-order-amt'); - const minCost = this.safeFloat (market, 'min-order-value', 0); + const minAmount = this.safeNumber (market, 'min-order-amt', Math.pow (10, -precision['amount'])); + const maxAmount = this.safeNumber (market, 'max-order-amt'); + const minCost = this.safeNumber (market, 'min-order-value', 0); const state = this.safeString (market, 'state'); const active = (state === 'online'); result.push ({ @@ -80581,24 +78968,24 @@ module.exports = class huobipro extends Exchange { let askVolume = undefined; if ('bid' in ticker) { if (Array.isArray (ticker['bid'])) { - bid = this.safeFloat (ticker['bid'], 0); - bidVolume = this.safeFloat (ticker['bid'], 1); + bid = this.safeNumber (ticker['bid'], 0); + bidVolume = this.safeNumber (ticker['bid'], 1); } else { - bid = this.safeFloat (ticker, 'bid'); + bid = this.safeNumber (ticker, 'bid'); bidVolume = this.safeValue (ticker, 'bidSize'); } } if ('ask' in ticker) { if (Array.isArray (ticker['ask'])) { - ask = this.safeFloat (ticker['ask'], 0); - askVolume = this.safeFloat (ticker['ask'], 1); + ask = this.safeNumber (ticker['ask'], 0); + askVolume = this.safeNumber (ticker['ask'], 1); } else { - ask = this.safeFloat (ticker, 'ask'); + ask = this.safeNumber (ticker, 'ask'); askVolume = this.safeValue (ticker, 'askSize'); } } - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -80609,15 +78996,15 @@ module.exports = class huobipro extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -80706,7 +79093,7 @@ module.exports = class huobipro extends Exchange { // } // const ticker = this.parseTicker (response['tick'], market); - const timestamp = this.safeValue (response, 'ts'); + const timestamp = this.safeInteger (response, 'ts'); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); return ticker; @@ -80775,21 +79162,18 @@ module.exports = class huobipro extends Exchange { type = typeParts[1]; } const takerOrMaker = this.safeString (trade, 'role'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'filled-amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'filled-amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - let feeCost = this.safeFloat (trade, 'filled-fees'); + let feeCost = this.safeNumber (trade, 'filled-fees'); let feeCurrency = undefined; if (market !== undefined) { feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-currency')); } - const filledPoints = this.safeFloat (trade, 'filled-points'); + const filledPoints = this.safeNumber (trade, 'filled-points'); if (filledPoints !== undefined) { if ((feeCost === undefined) || (feeCost === 0.0)) { feeCost = filledPoints; @@ -80903,11 +79287,11 @@ module.exports = class huobipro extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -81004,11 +79388,11 @@ module.exports = class huobipro extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'deposit-min-amount'), + 'min': this.safeNumber (currency, 'deposit-min-amount'), 'max': Math.pow (10, precision), }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw-min-amount'), + 'min': this.safeNumber (currency, 'withdraw-min-amount'), 'max': Math.pow (10, precision), }, }, @@ -81039,14 +79423,14 @@ module.exports = class huobipro extends Exchange { account = this.account (); } if (balance['type'] === 'trade') { - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); } if (balance['type'] === 'frozen') { - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrdersByStates (states, symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -81221,28 +79605,14 @@ module.exports = class huobipro extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (order, 'created-at'); - let amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount - if ((type === 'market') && (side === 'buy')) { - amount = (status === 'closed') ? filled : undefined; - } - let price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - const cost = this.safeFloat2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - // if cost is defined and filled is not zero - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - const feeCost = this.safeFloat2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees + const cost = this.safeNumber2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo + const feeCost = this.safeNumber2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -81254,7 +79624,7 @@ module.exports = class huobipro extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -81268,15 +79638,15 @@ module.exports = class huobipro extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -81350,26 +79720,82 @@ module.exports = class huobipro extends Exchange { }); } - currencyToPrecision (currency, fee) { - return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); + async cancelOrders (ids, symbol = undefined, params = {}) { + await this.loadMarkets (); + const clientOrderIds = this.safeValue2 (params, 'clientOrderIds', 'client-order-ids'); + params = this.omit (params, [ 'clientOrderIds', 'client-order-ids' ]); + const request = {}; + if (clientOrderIds === undefined) { + request['order-ids'] = ids; + } else { + request['client-order-ids'] = clientOrderIds; + } + const response = await this.privatePostOrderOrdersBatchcancel (this.extend (request, params)); + // + // { + // "status": "ok", + // "data": { + // "success": [ + // "5983466" + // ], + // "failed": [ + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "first" + // }, + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "second" + // }, + // { + // "err-msg": "The record is not found.", + // "order-id": "", + // "err-code": "base-not-found", + // "client-order-id": "third" + // } + // ] + // } + // } + // + return response; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (market[key], cost)), + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'account-id' string false NA The account id used for this cancel Refer to GET /v1/account/accounts + // 'symbol': market['id'], // a list of comma-separated symbols, all symbols by default + // 'types' 'string', buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok + // 'side': 'buy', // or 'sell' + // 'size': 100, // the number of orders to cancel 1-100 }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.privatePostOrderOrdersBatchCancelOpenOrders (this.extend (request, params)); + // + // { + // code: 200, + // data: { + // "success-count": 2, + // "failed-count": 0, + // "next-id": 5454600 + // } + // } + // + return response; + } + + currencyToPrecision (currency, fee) { + return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); } parseDepositAddress (depositAddress, currency = undefined) { @@ -81511,7 +79937,7 @@ module.exports = class huobipro extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const tag = this.safeString (transaction, 'address-tag'); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -81524,7 +79950,7 @@ module.exports = class huobipro extends Exchange { 'address': this.safeString (transaction, 'address'), 'tag': tag, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -81654,504 +80080,7 @@ module.exports = class huobipro extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],97:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class ice3x extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'ice3x', - 'name': 'ICE3X', - 'countries': [ 'ZA' ], // South Africa - 'rateLimit': 1000, - 'version': 'v1', - 'has': { - 'cancelOrder': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchCurrencies': true, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTrades': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg', - 'api': 'https://ice3x.com/api', - 'www': 'https://ice3x.com', // 'https://ice3x.co.za', - 'doc': 'https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017', - 'fees': [ - 'https://help.ice3.com/support/solutions/articles/11000033293-trading-fees', - 'https://help.ice3.com/support/solutions/articles/11000033288-fees-explained', - 'https://help.ice3.com/support/solutions/articles/11000008131-what-are-your-fiat-deposit-and-withdrawal-fees-', - 'https://help.ice3.com/support/solutions/articles/11000033289-deposit-fees', - ], - 'referral': 'https://ice3x.com?ref=14341802', - }, - 'api': { - 'public': { - 'get': [ - 'currency/list', - 'currency/info', - 'pair/list', - 'pair/info', - 'stats/marketdepthfull', - 'stats/marketdepthbtcav', - 'stats/marketdepth', - 'orderbook/info', - 'trade/list', - 'trade/info', - ], - }, - 'private': { - 'post': [ - 'balance/list', - 'balance/info', - 'order/new', - 'order/cancel', - 'order/list', - 'order/info', - 'trade/list', - 'trade/info', - 'transaction/list', - 'transaction/info', - 'invoice/list', - 'invoice/info', - 'invoice/pdf', - ], - }, - }, - 'fees': { - 'trading': { - 'maker': 0.005, - 'taker': 0.005, - }, - }, - 'precision': { - 'amount': 8, - 'price': 8, - }, - }); - } - - async fetchCurrencies (params = {}) { - const response = await this.publicGetCurrencyList (params); - const currencies = response['response']['entities']; - const precision = this.precision['amount']; - const result = {}; - for (let i = 0; i < currencies.length; i++) { - const currency = currencies[i]; - const id = this.safeString (currency, 'currency_id'); - const currencyId = this.safeString (currency, 'iso'); - const code = this.safeCurrencyCode (currencyId); - result[code] = { - 'id': id, - 'code': code, - 'name': currency['name'], - 'active': true, - 'precision': precision, - 'limits': { - 'amount': { - 'min': undefined, - 'max': Math.pow (10, precision), - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': Math.pow (10, precision), - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - }, - 'info': currency, - 'fee': undefined, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - if (this.currencies_by_id === undefined) { - this.currencies = await this.fetchCurrencies (); - this.currencies_by_id = this.indexBy (this.currencies, 'id'); - } - const response = await this.publicGetPairList (params); - const markets = this.safeValue (response['response'], 'entities'); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = this.safeString (market, 'pair_id'); - const baseId = this.safeString (market, 'currency_id_from'); - const quoteId = this.safeString (market, 'currency_id_to'); - const baseCurrency = this.currencies_by_id[baseId]; - const quoteCurrency = this.currencies_by_id[quoteId]; - const base = baseCurrency['code']; - const quote = quoteCurrency['code']; - const symbol = base + '/' + quote; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': undefined, - 'info': market, - 'precision': this.precision, - 'limits': this.limits, - }); - } - return result; - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.milliseconds (); - const symbol = market['symbol']; - const last = this.safeFloat (ticker, 'last_price'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'max_bid'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'min_ask'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'vol'), - 'info': ticker, - }; - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetStatsMarketdepthfull (this.extend (request, params)); - const ticker = this.safeValue (response['response'], 'entity'); - return this.parseTicker (ticker, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetStatsMarketdepthfull (params); - const tickers = this.safeValue (response['response'], 'entities'); - const result = {}; - for (let i = 0; i < tickers.length; i++) { - const ticker = tickers[i]; - const marketId = this.safeString (ticker, 'pair_id'); - const market = this.safeValue (this.marketsById, marketId); - if (market !== undefined) { - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); - } - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'pair_id': this.marketId (symbol), - }; - if (limit !== undefined) { - const type = this.safeString (params, 'type'); - if ((type !== 'ask') && (type !== 'bid')) { - // eslint-disable-next-line quotes - throw new ArgumentsRequired (this.id + " fetchOrderBook() requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit"); - } else { - request['items_per_page'] = limit; - } - } - const response = await this.publicGetOrderbookInfo (this.extend (request, params)); - const orderbook = this.safeValue (response['response'], 'entities'); - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.safeTimestamp (trade, 'created'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } - const type = 'limit'; - const side = this.safeString (trade, 'type'); - const id = this.safeString (trade, 'trade_id'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'id': id, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': type, - 'side': side, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetTradeList (this.extend (request, params)); - const trades = this.safeValue (response['response'], 'entities'); - return this.parseTrades (trades, market, since, limit); - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostBalanceList (params); - const result = { 'info': response }; - const balances = this.safeValue (response['response'], 'entities', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - // currency ids are numeric strings - const currencyId = this.safeString (balance, 'currency_id'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseOrder (order, market = undefined) { - const pairId = this.safeInteger (order, 'pair_id'); - let symbol = undefined; - if (pairId && !market && (pairId in this.marketsById)) { - market = this.marketsById[pairId]; - symbol = market['symbol']; - } - const timestamp = this.safeTimestamp (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - let status = this.safeInteger (order, 'active'); - let remaining = this.safeFloat (order, 'remaining'); - let filled = undefined; - if (status === 1) { - status = 'open'; - } else { - status = 'closed'; - remaining = 0; - filled = amount; - } - let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - }; - if (market !== undefined) { - fee['currency'] = market['quote']; - } - } - return { - 'id': this.safeString (order, 'order_id'), - 'clientOrderId': undefined, - 'datetime': this.iso8601 (timestamp), - 'timestamp': timestamp, - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': 'limit', - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': this.safeString (order, 'type'), - 'price': price, - 'stopPrice': undefined, - 'cost': undefined, - 'amount': amount, - 'filled': filled, - 'remaining': remaining, - 'trades': undefined, - 'fee': fee, - 'info': order, - 'average': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - 'type': side, - 'amount': amount, - 'price': price, - }; - const response = await this.privatePostOrderNew (this.extend (request, params)); - const order = this.parseOrder ({ - 'order_id': response['response']['entity']['order_id'], - 'created': this.seconds (), - 'active': 1, - 'type': side, - 'price': price, - 'volume': amount, - 'remaining': amount, - 'info': response, - }, market); - return order; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - const request = { - 'order_id': id, - }; - return await this.privatePostOrderCancel (this.extend (request, params)); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'order _id': id, - }; - const response = await this.privatePostOrderInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const order = this.safeValue (data, 'entity'); - return this.parseOrder (order); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.privatePostOrderList (params); - const data = this.safeValue (response, 'response', {}); - const orders = this.safeValue (data, 'entities', []); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - return this.parseOrders (orders, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - if (limit !== undefined) { - request['items_per_page'] = limit; - } - if (since !== undefined) { - request['date_from'] = parseInt (since / 1000); - } - const response = await this.privatePostTradeList (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const trades = this.safeValue (data, 'entities', []); - return this.parseTrades (trades, market, since, limit); - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency_id': currency['id'], - }; - const response = await this.privatePostBalanceInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const balance = this.safeValue (data, 'entity', {}); - const address = this.safeString (balance, 'address'); - const status = address ? 'ok' : 'none'; - return { - 'currency': code, - 'address': address, - 'tag': undefined, - 'status': status, - 'info': response, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/' + this.version + '/' + path; - if (api === 'public') { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } - } else { - this.checkRequiredCredentials (); - body = this.urlencode (this.extend ({ - 'nonce': this.nonce (), - }, params)); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const response = await this.fetch2 (path, api, method, params, headers, body); - const errors = this.safeValue (response, 'errors'); - const data = this.safeValue (response, 'response'); - if (errors || !data) { - const authErrorKeys = [ 'Key', 'user_id', 'Sign' ]; - for (let i = 0; i < authErrorKeys.length; i++) { - const errorKey = authErrorKeys[i]; - const errorMessage = this.safeString (errors, errorKey); - if (!errorMessage) { - continue; - } - if (errorKey === 'user_id' && errorMessage.indexOf ('authorization') < 0) { - continue; - } - throw new AuthenticationError (errorMessage); - } - throw new ExchangeError (this.json (errors)); - } - return response; - } -}; - -},{"./base/Exchange":6,"./base/errors":8}],98:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],95:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -82159,6 +80088,7 @@ module.exports = class ice3x extends Exchange { const Exchange = require ('./base/Exchange'); const { PAD_WITH_ZERO } = require ('./base/functions/number'); const { InvalidOrder, InsufficientFunds, ExchangeError, ExchangeNotAvailable, DDoSProtection, BadRequest, NotSupported, InvalidAddress, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -82395,14 +80325,6 @@ module.exports = class idex extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // { // market: 'DIL-ETH', @@ -82422,16 +80344,16 @@ module.exports = class idex extends Exchange { // } const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'baseVolume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'baseVolume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'open'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const close = this.safeFloat (ticker, 'close'); - const ask = this.safeFloat (ticker, 'ask'); - const bid = this.safeFloat (ticker, 'bid'); - let percentage = this.safeFloat (ticker, 'percentChange'); + const open = this.safeNumber (ticker, 'open'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const close = this.safeNumber (ticker, 'close'); + const ask = this.safeNumber (ticker, 'ask'); + const bid = this.safeNumber (ticker, 'bid'); + let percentage = this.safeNumber (ticker, 'percentChange'); if (percentage !== undefined) { percentage = 1 + percentage / 100; } @@ -82507,11 +80429,11 @@ module.exports = class idex extends Exchange { // sequence: 3853 // } const timestamp = this.safeInteger (ohlcv, 'start'); - const open = this.safeFloat (ohlcv, 'open'); - const high = this.safeFloat (ohlcv, 'high'); - const low = this.safeFloat (ohlcv, 'low'); - const close = this.safeFloat (ohlcv, 'close'); - const volume = this.safeFloat (ohlcv, 'volume'); + const open = this.safeNumber (ohlcv, 'open'); + const high = this.safeNumber (ohlcv, 'high'); + const low = this.safeNumber (ohlcv, 'low'); + const close = this.safeNumber (ohlcv, 'close'); + const volume = this.safeNumber (ohlcv, 'volume'); return [ timestamp, open, high, low, close, volume ]; } @@ -82573,9 +80495,14 @@ module.exports = class idex extends Exchange { // txStatus: 'mined' // } const id = this.safeString (trade, 'fillId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'quoteQuantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteQuantity'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const timestamp = this.safeInteger (trade, 'time'); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); @@ -82584,7 +80511,7 @@ module.exports = class idex extends Exchange { const oppositeSide = (makerSide === 'buy') ? 'sell' : 'buy'; const side = this.safeString (trade, 'side', oppositeSide); const takerOrMaker = this.safeString (trade, 'liquidity', 'taker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); @@ -82657,8 +80584,8 @@ module.exports = class idex extends Exchange { const result = []; for (let i = 0; i < bookSide.length; i++) { const order = bookSide[i]; - const price = this.safeFloat (order, 0); - const amount = this.safeFloat (order, 1); + const price = this.safeNumber (order, 0); + const amount = this.safeNumber (order, 1); const orderCount = this.safeInteger (order, 2); result.push ([ price, amount, orderCount ]); } @@ -82745,16 +80672,13 @@ module.exports = class idex extends Exchange { const entry = response[i]; const currencyId = this.safeString (entry, 'asset'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (entry, 'quantity'); - const free = this.safeFloat (entry, 'availableForTrade'); - const used = this.safeFloat (entry, 'locked'); - result[code] = { - 'free': free, - 'used': used, - 'total': total, - }; + const account = this.account (); + account['total'] = this.safeString (entry, 'quantity'); + account['free'] = this.safeString (entry, 'availableForTrade'); + account['used'] = this.safeString (entry, 'locked'); + result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -82975,10 +80899,10 @@ module.exports = class idex extends Exchange { const symbol = this.safeSymbol (marketId, market, '-'); const trades = this.parseTrades (fills, market); const type = this.safeString (order, 'type'); - const amount = this.safeFloat (order, 'originalQuantity'); - const filled = this.safeFloat (order, 'executedQuantity'); - const average = this.safeFloat (order, 'avgExecutionPrice'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'originalQuantity'); + const filled = this.safeNumber (order, 'executedQuantity'); + const average = this.safeNumber (order, 'avgExecutionPrice'); + const price = this.safeNumber (order, 'price'); const rawStatus = this.safeString (order, 'status'); const status = this.parseOrderStatus (rawStatus); const fee = { @@ -83087,7 +81011,7 @@ module.exports = class idex extends Exchange { throw new NotSupported (this.id + ' quoteOrderQuantity is not supported for ' + type + ' orders, only supported for market orders'); } amountEnum = 1; - amount = this.safeFloat (params, 'quoteOrderQuantity'); + amount = this.safeNumber (params, 'quoteOrderQuantity'); } const sideEnum = (side === 'buy') ? 0 : 1; const walletBytes = this.remove0xPrefix (this.walletAddress); @@ -83390,13 +81314,13 @@ module.exports = class idex extends Exchange { } const id = this.safeString2 (transaction, 'depositId', 'withdrawId'); const code = this.safeCurrencyCode (this.safeString (transaction, 'asset'), currency); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const txid = this.safeString (transaction, 'txId'); const timestamp = this.safeInteger (transaction, 'txTime'); let fee = undefined; if ('fee' in transaction) { fee = { - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), 'currency': 'ETH', }; } @@ -83454,12 +81378,13 @@ module.exports = class idex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],99:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],96:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -83583,11 +81508,11 @@ module.exports = class independentreserve extends Exchange { const currencyId = this.safeString (balance, 'CurrencyCode'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'AvailableBalance'); - account['total'] = this.safeFloat (balance, 'TotalBalance'); + account['free'] = this.safeString (balance, 'AvailableBalance'); + account['total'] = this.safeString (balance, 'TotalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -83608,16 +81533,16 @@ module.exports = class independentreserve extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'LastPrice'); + const last = this.safeNumber (ticker, 'LastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'DayHighestPrice'), - 'low': this.safeFloat (ticker, 'DayLowestPrice'), - 'bid': this.safeFloat (ticker, 'CurrentHighestBidPrice'), + 'high': this.safeNumber (ticker, 'DayHighestPrice'), + 'low': this.safeNumber (ticker, 'DayLowestPrice'), + 'bid': this.safeNumber (ticker, 'CurrentHighestBidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'CurrentLowestOfferPrice'), + 'ask': this.safeNumber (ticker, 'CurrentLowestOfferPrice'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -83626,8 +81551,8 @@ module.exports = class independentreserve extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'DayAvgPrice'), - 'baseVolume': this.safeFloat (ticker, 'DayVolumeXbtInSecondaryCurrrency'), + 'average': this.safeNumber (ticker, 'DayAvgPrice'), + 'baseVolume': this.safeNumber (ticker, 'DayVolumeXbtInSecondaryCurrrency'), 'quoteVolume': undefined, 'info': ticker, }; @@ -83706,20 +81631,10 @@ module.exports = class independentreserve extends Exchange { orderType = 'limit'; } const timestamp = this.parse8601 (this.safeString (order, 'CreatedTimestampUtc')); - const amount = this.safeFloat2 (order, 'VolumeOrdered', 'Volume'); - let filled = this.safeFloat (order, 'VolumeFilled'); - let remaining = this.safeFloat (order, 'Outstanding'); - if (filled === undefined) { - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (0, amount - remaining); - } - } - if (remaining === undefined) { - if ((filled !== undefined) && (amount !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const feeRate = this.safeFloat (order, 'FeePercent'); + const amount = this.safeNumber2 (order, 'VolumeOrdered', 'Volume'); + const filled = this.safeNumber (order, 'VolumeFilled'); + const remaining = this.safeNumber (order, 'Outstanding'); + const feeRate = this.safeNumber (order, 'FeePercent'); let feeCost = undefined; if (feeRate !== undefined) { feeCost = feeRate * filled; @@ -83731,10 +81646,10 @@ module.exports = class independentreserve extends Exchange { }; const id = this.safeString (order, 'OrderGuid'); const status = this.parseOrderStatus (this.safeString (order, 'Status')); - const cost = this.safeFloat (order, 'Value'); - const average = this.safeFloat (order, 'AvgPrice'); - const price = this.safeFloat (order, 'Price', average); - return { + const cost = this.safeNumber (order, 'Value'); + const average = this.safeNumber (order, 'AvgPrice'); + const price = this.safeNumber (order, 'Price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -83756,7 +81671,7 @@ module.exports = class independentreserve extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -83844,14 +81759,11 @@ module.exports = class independentreserve extends Exchange { const timestamp = this.parse8601 (trade['TradeTimestampUtc']); const id = this.safeString (trade, 'TradeGuid'); const orderId = this.safeString (trade, 'OrderGuid'); - const price = this.safeFloat2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); - const amount = this.safeFloat2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); + const amountString = this.safeString2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const baseId = this.safeString (trade, 'PrimaryCurrencyCode'); const quoteId = this.safeString (trade, 'SecondaryCurrencyCode'); let marketId = undefined; @@ -83964,13 +81876,14 @@ module.exports = class independentreserve extends Exchange { } }; -},{"./base/Exchange":6}],100:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],97:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, InvalidOrder, OrderNotFound, AuthenticationError, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -84131,7 +82044,7 @@ module.exports = class indodax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const taker = this.safeFloat (market, 'trade_fee_percent'); + const taker = this.safeNumber (market, 'trade_fee_percent'); const isMaintenance = this.safeInteger (market, 'is_maintenance'); const active = (isMaintenance) ? false : true; const pricePrecision = this.safeInteger (market, 'price_round'); @@ -84141,11 +82054,11 @@ module.exports = class indodax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'trade_min_traded_currency'), + 'min': this.safeNumber (market, 'trade_min_traded_currency'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'trade_min_base_currency'), + 'min': this.safeNumber (market, 'trade_min_base_currency'), 'max': undefined, }, 'cost': { @@ -84183,11 +82096,11 @@ module.exports = class indodax extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (used, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (used, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -84224,16 +82137,16 @@ module.exports = class indodax extends Exchange { const timestamp = this.safeTimestamp (ticker, 'server_time'); const baseVolume = 'vol_' + market['baseId'].toLowerCase (); const quoteVolume = 'vol_' + market['quoteId'].toLowerCase (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -84243,8 +82156,8 @@ module.exports = class indodax extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, baseVolume), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, baseVolume), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -84258,14 +82171,11 @@ module.exports = class indodax extends Exchange { } const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -84320,7 +82230,7 @@ module.exports = class indodax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status', 'open')); let symbol = undefined; let cost = undefined; - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let amount = undefined; let remaining = undefined; let filled = undefined; @@ -84334,18 +82244,18 @@ module.exports = class indodax extends Exchange { if ((market['baseId'] === 'idr') && ('remain_rp' in order)) { baseId = 'rp'; } - cost = this.safeFloat (order, 'order_' + quoteId); + cost = this.safeNumber (order, 'order_' + quoteId); if (cost) { amount = cost / price; - const remainingCost = this.safeFloat (order, 'remain_' + quoteId); + const remainingCost = this.safeNumber (order, 'remain_' + quoteId); if (remainingCost !== undefined) { remaining = remainingCost / price; filled = amount - remaining; } } else { - amount = this.safeFloat (order, 'order_' + baseId); + amount = this.safeNumber (order, 'order_' + baseId); cost = price * amount; - remaining = this.safeFloat (order, 'remain_' + baseId); + remaining = this.safeNumber (order, 'remain_' + baseId); filled = amount - remaining; } } @@ -84585,13 +82495,14 @@ module.exports = class indodax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],101:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],98:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -84702,25 +82613,25 @@ module.exports = class itbit extends Exchange { throw new ExchangeError (this.id + ' fetchTicker returned a bad response: ' + this.json (ticker)); } const timestamp = this.parse8601 (serverTimeUTC); - const vwap = this.safeFloat (ticker, 'vwap24h'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); + const vwap = this.safeNumber (ticker, 'vwap24h'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'openToday'), + 'open': this.safeNumber (ticker, 'openToday'), 'close': last, 'last': last, 'previousClose': undefined, @@ -84767,23 +82678,20 @@ module.exports = class itbit extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const side = this.safeString (trade, 'direction'); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'commissionPaid'); + let feeCost = this.safeNumber (trade, 'commissionPaid'); const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - let rebatesApplied = this.safeFloat (trade, 'rebatesApplied'); + let rebatesApplied = this.safeNumber (trade, 'rebatesApplied'); if (rebatesApplied !== undefined) { rebatesApplied = -rebatesApplied; } const rebateCurrencyId = this.safeString (trade, 'rebateCurrency'); const rebateCurrency = this.safeCurrencyCode (rebateCurrencyId); - const price = this.safeFloat2 (trade, 'price', 'rate'); - const amount = this.safeFloat2 (trade, 'currency1Amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'price', 'rate'); + const amountString = this.safeString2 (trade, 'currency1Amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; const marketId = this.safeString (trade, 'instrument'); if (marketId !== undefined) { @@ -84905,7 +82813,7 @@ module.exports = class itbit extends Exchange { 'txid': txnHash, 'type': transactionType, 'status': status, - 'amount': this.safeFloat (item, 'amount'), + 'amount': this.safeNumber (item, 'amount'), 'fee': undefined, 'info': item, }); @@ -85005,11 +82913,11 @@ module.exports = class itbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchWallets (params = {}) { @@ -85100,26 +83008,16 @@ module.exports = class itbit extends Exchange { const type = this.safeString (order, 'type'); const symbol = this.markets_by_id[order['instrument']]['symbol']; const timestamp = this.parse8601 (order['createdTime']); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'amountFilled'); - let remaining = undefined; - let cost = undefined; + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'amountFilled'); const fee = undefined; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'volumeWeightedAveragePrice'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'volumeWeightedAveragePrice'); const clientOrderId = this.safeString (order, 'clientOrderIdentifier'); const id = this.safeString (order, 'id'); const postOnlyString = this.safeString (order, 'postOnly'); const postOnly = (postOnlyString === 'True'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -85134,15 +83032,15 @@ module.exports = class itbit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, // 'trades': this.parseTrades (order['trades'], market), 'trades': undefined, - }; + }); } nonce () { @@ -85240,7 +83138,7 @@ module.exports = class itbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],102:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],99:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -85248,6 +83146,7 @@ module.exports = class itbit extends Exchange { const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeNotAvailable, ArgumentsRequired, PermissionDenied, AuthenticationError, ExchangeError, OrderNotFound, DDoSProtection, InvalidNonce, InsufficientFunds, CancelPending, InvalidOrder, InvalidAddress, RateLimitExceeded } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -85540,26 +83439,38 @@ module.exports = class kraken extends Exchange { // } // } // - const keys = Object.keys (response['result']); + const markets = this.safeValue (response, 'result', {}); + const keys = Object.keys (markets); let result = []; for (let i = 0; i < keys.length; i++) { const id = keys[i]; - const market = response['result'][id]; - const baseId = market['base']; - const quoteId = market['quote']; + const market = markets[id]; + const baseId = this.safeString (market, 'base'); + const quoteId = this.safeString (market, 'quote'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const darkpool = id.indexOf ('.d') >= 0; - const symbol = darkpool ? market['altname'] : (base + '/' + quote); + const altname = this.safeString (market, 'altname'); + const symbol = darkpool ? altname : (base + '/' + quote); + const makerFees = this.safeValue (market, 'fees_maker', []); + const firstMakerFee = this.safeValue (makerFees, 0, []); + const firstMakerFeeRate = this.safeNumber (firstMakerFee, 1); let maker = undefined; - if ('fees_maker' in market) { - maker = parseFloat (market['fees_maker'][0][1]) / 100; + if (firstMakerFeeRate !== undefined) { + maker = parseFloat (firstMakerFeeRate) / 100; + } + const takerFees = this.safeValue (market, 'fees', []); + const firstTakerFee = this.safeValue (takerFees, 0, []); + const firstTakerFeeRate = this.safeNumber (firstTakerFee, 1); + let taker = undefined; + if (firstTakerFeeRate !== undefined) { + taker = parseFloat (firstTakerFeeRate) / 100; } const precision = { - 'amount': market['lot_decimals'], - 'price': market['pair_decimals'], + 'amount': this.safeInteger (market, 'lot_decimals'), + 'price': this.safeInteger (market, 'pair_decimals'), }; - const minAmount = this.safeFloat (market, 'ordermin'); + const minAmount = this.safeNumber (market, 'ordermin'); result.push ({ 'id': id, 'symbol': symbol, @@ -85571,7 +83482,7 @@ module.exports = class kraken extends Exchange { 'info': market, 'altname': market['altname'], 'maker': maker, - 'taker': parseFloat (market['fees'][0][1]) / 100, + 'taker': taker, 'active': true, 'precision': precision, 'limits': { @@ -85694,7 +83605,7 @@ module.exports = class kraken extends Exchange { await this.loadMarkets (); this.checkRequiredCredentials (); const response = await this.privatePostTradeVolume (params); - const tradedVolume = this.safeFloat (response['result'], 'volume'); + const tradedVolume = this.safeNumber (response['result'], 'volume'); const tiers = this.fees['trading']['tiers']; let taker = tiers['taker'][1]; let maker = tiers['maker'][1]; @@ -85716,8 +83627,8 @@ module.exports = class kraken extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); const timestamp = this.safeInteger (bidask, 2); return [ price, amount, timestamp ]; } @@ -85755,7 +83666,14 @@ module.exports = class kraken extends Exchange { // } // const result = this.safeValue (response, 'result', {}); - const orderbook = this.safeValue (result, market['id']); + let orderbook = this.safeValue (result, market['id']); + // sometimes kraken returns wsname instead of market id + // https://github.com/ccxt/ccxt/issues/8662 + const marketInfo = this.safeValue (market, 'info', {}); + const wsName = this.safeValue (marketInfo, 'wsname'); + if (wsName !== undefined) { + orderbook = this.safeValue (result, wsName, orderbook); + } return this.parseOrderBook (orderbook); } @@ -85783,7 +83701,7 @@ module.exports = class kraken extends Exchange { 'ask': parseFloat (ticker['a'][0]), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'o'), + 'open': this.safeNumber (ticker, 'o'), 'close': last, 'last': last, 'previousClose': undefined, @@ -85854,11 +83772,11 @@ module.exports = class kraken extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 6), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 6), ]; } @@ -85925,24 +83843,24 @@ module.exports = class kraken extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'asset'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); } else { direction = 'in'; } - const time = this.safeFloat (item, 'time'); + const time = this.safeNumber (item, 'time'); let timestamp = undefined; if (time !== undefined) { timestamp = parseInt (time * 1000); } const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -86066,9 +83984,8 @@ module.exports = class kraken extends Exchange { let timestamp = undefined; let side = undefined; let type = undefined; - let price = undefined; - let amount = undefined; - let cost = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; let orderId = undefined; let fee = undefined; @@ -86077,8 +83994,8 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 2); side = (trade[3] === 's') ? 'sell' : 'buy'; type = (trade[4] === 'l') ? 'limit' : 'market'; - price = this.safeFloat (trade, 0); - amount = this.safeFloat (trade, 1); + priceString = this.safeString (trade, 0); + amountString = this.safeString (trade, 1); const tradeLength = trade.length; if (tradeLength > 6) { id = this.safeString (trade, 6); // artificially added as per #1794 @@ -86099,15 +84016,15 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 'time'); side = this.safeString (trade, 'type'); type = this.safeString (trade, 'ordertype'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'vol'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'vol'); if ('fee' in trade) { let currency = undefined; if (market !== undefined) { currency = market['quote']; } fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': currency, }; } @@ -86115,11 +84032,9 @@ module.exports = class kraken extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': orderId, @@ -86194,10 +84109,10 @@ module.exports = class kraken extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -86226,15 +84141,15 @@ module.exports = class kraken extends Exchange { if (type === 'limit') { request['price'] = this.priceToPrecision (symbol, price); } else if ((type === 'stop-loss') || (type === 'take-profit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice', price); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice', price); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument or a price/stopPrice parameter for a ' + type + ' order'); } else { request['price'] = this.priceToPrecision (symbol, stopPrice); } } else if ((type === 'stop-loss-limit') || (type === 'take-profit-limit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice'); - const limitPrice = this.safeFloat (params, 'price2'); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice'); + const limitPrice = this.safeNumber (params, 'price2'); const stopPriceDefined = (stopPrice !== undefined); const limitPriceDefined = (limitPrice !== undefined); if (stopPriceDefined && limitPriceDefined) { @@ -86343,10 +84258,10 @@ module.exports = class kraken extends Exchange { if (orderDescription !== undefined) { const parts = orderDescription.split (' '); side = this.safeString (parts, 0); - amount = this.safeFloat (parts, 1); + amount = this.safeNumber (parts, 1); marketId = this.safeString (parts, 2); type = this.safeString (parts, 4); - price = this.safeFloat (parts, 5); + price = this.safeNumber (parts, 5); } side = this.safeString (description, 'type', side); type = this.safeString (description, 'ordertype', type); @@ -86360,27 +84275,23 @@ module.exports = class kraken extends Exchange { market = this.getDelistedMarketById (marketId); } const timestamp = this.safeTimestamp (order, 'opentm'); - amount = this.safeFloat (order, 'vol', amount); - const filled = this.safeFloat (order, 'vol_exec'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = amount - filled; - } + amount = this.safeNumber (order, 'vol', amount); + const filled = this.safeNumber (order, 'vol_exec'); let fee = undefined; - const cost = this.safeFloat (order, 'cost'); - price = this.safeFloat (description, 'price', price); + const cost = this.safeNumber (order, 'cost'); + price = this.safeNumber (description, 'price', price); if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (description, 'price2'); + price = this.safeNumber (description, 'price2'); } if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (order, 'price', price); + price = this.safeNumber (order, 'price', price); } - const average = this.safeFloat (order, 'price'); + const average = this.safeNumber (order, 'price'); if (market !== undefined) { symbol = market['symbol']; if ('fee' in order) { const flags = order['oflags']; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); fee = { 'cost': feeCost, 'rate': undefined, @@ -86404,8 +84315,8 @@ module.exports = class kraken extends Exchange { if (rawTrades !== undefined) { trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id }); } - const stopPrice = this.safeFloat (order, 'stopprice'); - return { + const stopPrice = this.safeNumber (order, 'stopprice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -86424,10 +84335,10 @@ module.exports = class kraken extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -86777,10 +84688,10 @@ module.exports = class kraken extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const address = this.safeString (transaction, 'info'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.safeString (transaction, 'type'); // injected from the outside - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost === undefined) { if (type === 'deposit') { feeCost = 0; @@ -86957,7 +84868,7 @@ module.exports = class kraken extends Exchange { throw new ExchangeError (this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)"); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { // 'txid': 'comma delimited list of transaction ids to restrict output to', @@ -87091,13 +85002,14 @@ module.exports = class kraken extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],103:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],100:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -87139,6 +85051,7 @@ module.exports = class kucoin extends Exchange { 'fetchTrades': true, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg', @@ -87146,6 +85059,7 @@ module.exports = class kucoin extends Exchange { 'api': { 'public': 'https://openapi-v2.kucoin.com', 'private': 'https://openapi-v2.kucoin.com', + 'futuresPrivate': 'https://api-futures.kucoin.com', }, 'test': { 'public': 'https://openapi-sandbox.kucoin.com', @@ -87254,6 +85168,15 @@ module.exports = class kucoin extends Exchange { 'stop-order/cancel', ], }, + 'futuresPrivate': { + 'get': [ + 'account-overview', + 'positions', + ], + 'post': [ + 'transfer-out', + ], + }, }, 'timeframes': { '1m': '1min', @@ -87278,6 +85201,7 @@ module.exports = class kucoin extends Exchange { 'order_not_exist_or_not_allow_to_cancel': InvalidOrder, // {"code":"400100","msg":"order_not_exist_or_not_allow_to_cancel"} 'Order size below the minimum requirement.': InvalidOrder, // {"code":"400100","msg":"Order size below the minimum requirement."} 'The withdrawal amount is below the minimum requirement.': ExchangeError, // {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."} + 'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, // {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"} '400': BadRequest, '401': AuthenticationError, '403': NotSupported, @@ -87334,9 +85258,7 @@ module.exports = class kucoin extends Exchange { 'version': 'v1', 'symbolSeparator': '-', 'fetchMyTradesMethod': 'private_get_fills', - 'fetchBalance': { - 'type': 'trade', // or 'main' - }, + 'fetchBalance': 'trade', // endpoint versions 'versions': { 'public': { @@ -87356,6 +85278,25 @@ module.exports = class kucoin extends Exchange { 'accounts/sub-transfer': 'v2', }, }, + 'futuresPrivate': { + 'GET': { + 'account-overview': 'v1', + 'positions': 'v1', + }, + 'POST': { + 'transfer-out': 'v2', + }, + }, + }, + 'accountsByType': { + 'trade': 'trade', + 'trading': 'trade', + 'margin': 'margin', + 'main': 'main', + 'futures': 'contract', + 'contract': 'contract', + 'pool': 'pool', + 'pool-x': 'pool', }, }, }); @@ -87436,11 +85377,11 @@ module.exports = class kucoin extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const active = this.safeValue (market, 'enableTrading'); - const baseMaxSize = this.safeFloat (market, 'baseMaxSize'); - const baseMinSize = this.safeFloat (market, 'baseMinSize'); - const quoteMaxSize = this.safeFloat (market, 'quoteMaxSize'); - const quoteMinSize = this.safeFloat (market, 'quoteMinSize'); - // const quoteIncrement = this.safeFloat (market, 'quoteIncrement'); + const baseMaxSize = this.safeNumber (market, 'baseMaxSize'); + const baseMinSize = this.safeNumber (market, 'baseMinSize'); + const quoteMaxSize = this.safeNumber (market, 'quoteMaxSize'); + const quoteMinSize = this.safeNumber (market, 'quoteMinSize'); + // const quoteIncrement = this.safeNumber (market, 'quoteIncrement'); const precision = { 'amount': this.precisionFromString (this.safeString (market, 'baseIncrement')), 'price': this.precisionFromString (this.safeString (market, 'priceIncrement')), @@ -87451,7 +85392,7 @@ module.exports = class kucoin extends Exchange { 'max': baseMaxSize, }, 'price': { - 'min': this.safeFloat (market, 'priceIncrement'), + 'min': this.safeNumber (market, 'priceIncrement'), 'max': quoteMaxSize / baseMinSize, }, 'cost': { @@ -87502,7 +85443,7 @@ module.exports = class kucoin extends Exchange { const precision = this.safeInteger (entry, 'precision'); const isWithdrawEnabled = this.safeValue (entry, 'isWithdrawEnabled', false); const isDepositEnabled = this.safeValue (entry, 'isDepositEnabled', false); - const fee = this.safeFloat (entry, 'withdrawalMinFee'); + const fee = this.safeNumber (entry, 'withdrawalMinFee'); const active = (isWithdrawEnabled && isDepositEnabled); result[code] = { 'id': id, @@ -87569,7 +85510,7 @@ module.exports = class kucoin extends Exchange { const response = await this.privateGetWithdrawalsQuotas (this.extend (request, params)); const data = response['data']; const withdrawFees = {}; - withdrawFees[code] = this.safeFloat (data, 'withdrawMinFee'); + withdrawFees[code] = this.safeNumber (data, 'withdrawMinFee'); return { 'info': response, 'withdraw': withdrawFees, @@ -87616,35 +85557,35 @@ module.exports = class kucoin extends Exchange { // "mark": 0 // } // - let percentage = this.safeFloat (ticker, 'changeRate'); + let percentage = this.safeNumber (ticker, 'changeRate'); if (percentage !== undefined) { percentage = percentage * 100; } - const last = this.safeFloat2 (ticker, 'last', 'lastTradedPrice'); + const last = this.safeNumber2 (ticker, 'last', 'lastTradedPrice'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'vol'); - const quoteVolume = this.safeFloat (ticker, 'volValue'); + const baseVolume = this.safeNumber (ticker, 'vol'); + const quoteVolume = this.safeNumber (ticker, 'volValue'); const vwap = this.vwap (baseVolume, quoteVolume); const timestamp = this.safeInteger2 (ticker, 'time', 'datetime'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'changePrice'), + 'change': this.safeNumber (ticker, 'changePrice'), 'percentage': percentage, - 'average': this.safeFloat (ticker, 'averagePrice'), + 'average': this.safeNumber (ticker, 'averagePrice'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -87728,11 +85669,11 @@ module.exports = class kucoin extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -87930,16 +85871,18 @@ module.exports = class kucoin extends Exchange { // 'marginMode': 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned // 'autoBorrow': false, // The system will first borrow you funds at the optimal interest rate and then place an order for you }; - if (type !== 'market') { - request['price'] = this.priceToPrecision (symbol, price); - request['size'] = this.amountToPrecision (symbol, amount); - } else { - if (this.safeValue (params, 'quoteAmount')) { - // used to create market order by quote amount - https://github.com/ccxt/ccxt/issues/4876 - request['funds'] = this.amountToPrecision (symbol, amount); + const quoteAmount = this.safeNumber2 (params, 'cost', 'funds'); + if (type === 'market') { + if (quoteAmount !== undefined) { + params = this.omit (params, [ 'cost', 'funds' ]); + // kucoin uses base precision even for quote values + request['funds'] = this.amountToPrecision (symbol, quoteAmount); } else { request['size'] = this.amountToPrecision (symbol, amount); } + } else { + request['price'] = this.priceToPrecision (symbol, price); + request['size'] = this.amountToPrecision (symbol, amount); } const response = await this.privatePostOrders (this.extend (request, params)); // @@ -87973,8 +85916,10 @@ module.exports = class kucoin extends Exchange { 'fee': undefined, 'trades': undefined, }; - if (!this.safeValue (params, 'quoteAmount')) { + if (quoteAmount === undefined) { order['amount'] = amount; + } else { + order['cost'] = quoteAmount; } return order; } @@ -88150,15 +86095,18 @@ module.exports = class kucoin extends Exchange { const type = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'createdAt'); const datetime = this.iso8601 (timestamp); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); + if (price === 0.0) { + // market orders + price = undefined; + } const side = this.safeString (order, 'side'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (order, 'fee'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'dealSize'); - const cost = this.safeFloat (order, 'dealFunds'); - const remaining = amount - filled; + const feeCost = this.safeNumber (order, 'fee'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'dealSize'); + const cost = this.safeNumber (order, 'dealFunds'); // bool const isActive = this.safeValue (order, 'isActive', false); const cancelExist = this.safeValue (order, 'cancelExist', false); @@ -88168,20 +86116,11 @@ module.exports = class kucoin extends Exchange { 'currency': feeCurrency, 'cost': feeCost, }; - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const clientOrderId = this.safeString (order, 'clientOid'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': orderId, 'clientOrderId': clientOrderId, 'symbol': symbol, @@ -88194,7 +86133,7 @@ module.exports = class kucoin extends Exchange { 'stopPrice': stopPrice, 'cost': cost, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'timestamp': timestamp, 'datetime': datetime, 'fee': fee, @@ -88203,7 +86142,7 @@ module.exports = class kucoin extends Exchange { 'lastTradeTimestamp': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -88404,7 +86343,6 @@ module.exports = class kucoin extends Exchange { const id = this.safeString2 (trade, 'tradeId', 'id'); const orderId = this.safeString (trade, 'orderId'); const takerOrMaker = this.safeString (trade, 'liquidity'); - const amount = this.safeFloat2 (trade, 'size', 'amount'); let timestamp = this.safeInteger (trade, 'time'); if (timestamp !== undefined) { timestamp = parseInt (timestamp / 1000000); @@ -88415,10 +86353,13 @@ module.exports = class kucoin extends Exchange { timestamp = timestamp * 1000; } } - const price = this.safeFloat2 (trade, 'price', 'dealPrice'); + const priceString = this.safeString2 (trade, 'price', 'dealPrice'); + const amountString = this.safeString2 (trade, 'size', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const side = this.safeString (trade, 'side'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); let feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -88430,20 +86371,16 @@ module.exports = class kucoin extends Exchange { fee = { 'cost': feeCost, 'currency': feeCurrency, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } let type = this.safeString (trade, 'type'); if (type === 'match') { type = undefined; } - let cost = this.safeFloat2 (trade, 'funds', 'dealValue'); + let cost = this.safeNumber2 (trade, 'funds', 'dealValue'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'info': trade, @@ -88539,7 +86476,7 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); let address = this.safeString (transaction, 'address'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let txid = this.safeString (transaction, 'walletTxId'); if (txid !== undefined) { const txidParts = txid.split ('@'); @@ -88557,7 +86494,7 @@ module.exports = class kucoin extends Exchange { const rawStatus = this.safeString (transaction, 'status'); const status = this.parseTransactionStatus (rawStatus); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { let rate = undefined; if (amount !== undefined) { @@ -88738,45 +86675,180 @@ module.exports = class kucoin extends Exchange { async fetchBalance (params = {}) { await this.loadMarkets (); - let type = undefined; - const request = {}; - if ('type' in params) { - type = params['type']; - if (type !== undefined) { - request['type'] = type; - } - params = this.omit (params, 'type'); + const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'trade'); + const requestedType = this.safeString (params, 'type', defaultType); + const accountsByType = this.safeValue (this.options, 'accountsByType'); + const type = this.safeString (accountsByType, requestedType); + if (type === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' type must be one of ' + keys.join (', ')); + } + params = this.omit (params, 'type'); + if (type === 'contract') { + // futures api requires a futures apiKey + // only fetches one balance at a time + // by default it will only fetch the BTC balance of the futures account + // you can send 'currency' in params to fetch other currencies + // fetchBalance ({ 'type': 'futures', 'currency': 'USDT' }) + const response = await this.futuresPrivateGetAccountOverview (params); + // + // { + // code: '200000', + // data: { + // accountEquity: 0.00005, + // unrealisedPNL: 0, + // marginBalance: 0.00005, + // positionMargin: 0, + // orderMargin: 0, + // frozenFunds: 0, + // availableBalance: 0.00005, + // currency: 'XBT' + // } + // } + // + const data = this.safeValue (response, 'data'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (data, 'availableBalance'); + account['total'] = this.safeString (data, 'accountEquity'); + const result = { 'info': response }; + result[code] = account; + return this.parseBalance (result, false); } else { - const options = this.safeValue (this.options, 'fetchBalance', {}); - type = this.safeString (options, 'type', 'trade'); - } - const response = await this.privateGetAccounts (this.extend (request, params)); - // - // { - // "code":"200000", - // "data":[ - // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, - // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, - // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - const result = { 'info': response }; - for (let i = 0; i < data.length; i++) { - const balance = data[i]; - const balanceType = this.safeString (balance, 'type'); - if (balanceType === type) { - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'holds'); - result[code] = account; + const request = { + 'type': type, + }; + const response = await this.privateGetAccounts (this.extend (request, params)); + // + // { + // "code":"200000", + // "data":[ + // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, + // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, + // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + const result = { 'info': response }; + for (let i = 0; i < data.length; i++) { + const balance = data[i]; + const balanceType = this.safeString (balance, 'type'); + if (balanceType === type) { + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'holds'); + result[code] = account; + } } + return this.parseBalance (result, false); + } + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const requestedAmount = this.currencyToPrecision (code, amount); + const accountsById = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsById, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsById, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + if (fromId === 'contract') { + if (toId !== 'main') { + throw new ExchangeError (this.id + ' only supports transferring from futures account to main account'); + } + const request = { + 'currency': currency['id'], + 'amount': requestedAmount, + }; + if (!('bizNo' in params)) { + // it doesn't like more than 24 characters + request['bizNo'] = this.uuid22 (); + } + const response = await this.futuresPrivatePostTransferOut (this.extend (request, params)); + // + // { + // code: '200000', + // data: { + // applyId: '605a87217dff1500063d485d', + // bizNo: 'bcd6e5e1291f4905af84dc', + // payAccountType: 'CONTRACT', + // payTag: 'DEFAULT', + // remark: '', + // recAccountType: 'MAIN', + // recTag: 'DEFAULT', + // recRemark: '', + // recSystem: 'KUCOIN', + // status: 'PROCESSING', + // currency: 'XBT', + // amount: '0.00001', + // fee: '0', + // sn: '573688685663948', + // reason: '', + // createdAt: 1616545569000, + // updatedAt: 1616545569000 + // } + // } + // + const data = this.safeValue (response, 'data'); + const timestamp = this.safeInteger (data, 'createdAt'); + const id = this.safeString (data, 'applyId'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const amount = this.safeNumber (data, 'amount'); + const rawStatus = this.safeString (data, 'status'); + let status = undefined; + if (rawStatus === 'PROCESSING') { + status = 'pending'; + } + return { + 'info': response, + 'currency': code, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'amount': amount, + 'fromAccount': fromId, + 'toAccount': toId, + 'id': id, + 'status': status, + }; + } else { + const request = { + 'currency': currency['id'], + 'from': fromId, + 'to': toId, + 'amount': requestedAmount, + }; + if (!('clientOid' in params)) { + request['clientOid'] = this.uuid (); + } + const response = await this.privatePostAccountsInnerTransfer (this.extend (request, params)); + // { code: '200000', data: { orderId: '605a6211e657f00006ad0ad6' } } + const data = this.safeValue (response, 'data'); + const id = this.safeString (data, 'orderId'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'currency': code, + 'amount': requestedAmount, + 'fromAccount': fromId, + 'toAccount': toId, + 'status': undefined, + }; } - return this.parseBalance (result); } async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -88864,11 +86936,11 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'code': code, }; - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'balance'); const direction = this.safeString (item, 'direction'); let before = undefined; if (after !== undefined && amount !== undefined) { @@ -88918,6 +86990,94 @@ module.exports = class kucoin extends Exchange { return this.safeString (types, type, type); } + async fetchPositions (symbols = undefined, params = {}) { + const response = await this.futuresPrivateGetPositions (params); + // + // { + // code: '200000', + // data: [ + // { + // id: '605a9772a229ab0006408258', + // symbol: 'XBTUSDTM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746099, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54371.92, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'USDT', + // isInverse: false + // }, + // { + // id: '605a9772026ac900066550df', + // symbol: 'XBTUSDM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746110, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54354.76, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'XBT', + // isInverse: true + // } + // ] + // } + // + return this.safeValue (response, 'data', response); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { // // the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint @@ -88934,16 +87094,16 @@ module.exports = class kucoin extends Exchange { let endpart = ''; headers = (headers !== undefined) ? headers : {}; if (Object.keys (query).length) { - if (method !== 'GET') { + if ((method === 'GET') || (method === 'DELETE')) { + endpoint += '?' + this.urlencode (query); + } else { body = this.json (query); endpart = body; headers['Content-Type'] = 'application/json'; - } else { - endpoint += '?' + this.urlencode (query); } } const url = this.urls['api'][api] + endpoint; - if (api === 'private') { + if ((api === 'private') || (api === 'futuresPrivate')) { this.checkRequiredCredentials (); const timestamp = this.nonce ().toString (); headers = this.extend ({ @@ -88986,23 +87146,24 @@ module.exports = class kucoin extends Exchange { // { code: '200000', data: { ... }} // const errorCode = this.safeString (response, 'code'); - const message = this.safeString (response, 'msg'); - this.throwExactlyMatchedException (this.exceptions['exact'], message, message); - this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, message); + const message = this.safeString (response, 'msg', ''); + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, this.id + ' ' + message); } }; -},{"./base/Exchange":6,"./base/errors":8}],104:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],101:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- -const acx = require ('./acx.js'); -const { ArgumentsRequired } = require ('./base/errors'); +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, InsufficientFunds, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class kuna extends acx { +module.exports = class kuna extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'kuna', @@ -89012,14 +87173,24 @@ module.exports = class kuna extends acx { 'version': 'v2', 'has': { 'CORS': false, - 'fetchTickers': true, + 'cancelOrder': true, + 'createOrder': true, + 'fetchBalance': true, + 'fetchMarkets': true, + 'fetchMyTrades': true, 'fetchOHLCV': 'emulated', 'fetchOpenOrders': true, - 'fetchMyTrades': true, + 'fetchOrder': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchTime': true, + 'fetchTrades': true, 'withdraw': false, }, 'timeframes': undefined, 'urls': { + 'extension': '.json', 'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4', 'logo': 'https://user-images.githubusercontent.com/51840849/87153927-f0578b80-c2c0-11ea-84b6-74612568e9e1.jpg', 'api': 'https://kuna.io', @@ -89027,8 +87198,47 @@ module.exports = class kuna extends acx { 'doc': 'https://kuna.io/documents/api', 'fees': 'https://kuna.io/documents/api', }, + 'api': { + 'public': { + 'get': [ + 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. + 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator + 'k', // Get OHLC(k line) of specific market + 'markets', // Get all available markets + 'order_book', // Get the order book of specified market + 'order_book/{market}', + 'tickers', // Get ticker of all markets + 'tickers/{market}', // Get ticker of specific market + 'timestamp', // Get server current time, in seconds since Unix epoch + 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. + 'trades/{market}', + ], + }, + 'private': { + 'get': [ + 'members/me', // Get your profile and accounts info + 'deposits', // Get your deposits history + 'deposit', // Get details of specific deposit + 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. + 'orders', // Get your orders, results is paginated + 'order', // Get information of specified order + 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. + 'withdraws', // Get your cryptocurrency withdraws + 'withdraw', // Get your cryptocurrency withdraw + ], + 'post': [ + 'orders', // Create a Sell/Buy order + 'orders/multi', // Create multiple sell/buy orders + 'orders/clear', // Cancel all my orders + 'order/delete', // Cancel an order + 'withdraw', // Create a withdraw + ], + }, + }, 'fees': { 'trading': { + 'tierBased': false, + 'percentage': true, 'taker': 0.25 / 100, 'maker': 0.25 / 100, }, @@ -89051,9 +87261,24 @@ module.exports = class kuna extends acx { }, }, }, + 'commonCurrencies': { + 'PLA': 'Plair', + }, + 'exceptions': { + '2002': InsufficientFunds, + '2003': OrderNotFound, + }, }); } + async fetchTime (params = {}) { + const response = await this.publicGetTimestamp (params); + // + // 1594911427 + // + return response * 1000; + } + async fetchMarkets (params = {}) { const quotes = [ 'btc', 'eth', 'eurs', 'rub', 'uah', 'usd', 'usdt', 'gol' ]; const pricePrecisions = { @@ -89109,24 +87334,100 @@ module.exports = class kuna extends acx { return markets; } - async fetchL3OrderBook (symbol, limit = undefined, params = {}) { - return await this.fetchOrderBook (symbol, limit, params); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); - } + async fetchOrderBook (symbol, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; - const response = await this.privateGetOrders (this.extend (request, params)); - // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder - // with order cache + fetchOpenOrders - // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX - return this.parseOrders (response, market, since, limit); + if (limit !== undefined) { + request['limit'] = limit; // default = 300 + } + const orderbook = await this.publicGetDepth (this.extend (request, params)); + const timestamp = this.safeTimestamp (orderbook, 'timestamp'); + return this.parseOrderBook (orderbook, timestamp); + } + + parseTicker (ticker, market = undefined) { + const timestamp = this.safeTimestamp (ticker, 'at'); + ticker = ticker['ticker']; + let symbol = undefined; + if (market) { + symbol = market['symbol']; + } + const last = this.safeNumber (ticker, 'last'); + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'bidVolume': undefined, + 'ask': this.safeNumber (ticker, 'sell'), + 'askVolume': undefined, + 'vwap': undefined, + 'open': this.safeNumber (ticker, 'open'), + 'close': last, + 'last': last, + 'previousClose': undefined, + 'change': undefined, + 'percentage': undefined, + 'average': undefined, + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const response = await this.publicGetTickers (params); + const ids = Object.keys (response); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + let market = undefined; + let symbol = id; + if (id in this.markets_by_id) { + market = this.markets_by_id[id]; + symbol = market['symbol']; + } else { + let base = id.slice (0, 3); + let quote = id.slice (3, 6); + base = base.toUpperCase (); + quote = quote.toUpperCase (); + base = this.safeCurrencyCode (base); + quote = this.safeCurrencyCode (quote); + symbol = base + '/' + quote; + } + result[symbol] = this.parseTicker (response[id], market); + } + return this.filterByArray (result, 'symbol', symbols); + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTickersMarket (this.extend (request, params)); + return this.parseTicker (response, market); + } + + async fetchL3OrderBook (symbol, limit = undefined, params = {}) { + return await this.fetchOrderBook (symbol, limit, params); + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTrades (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); } parseTrade (trade, market = undefined) { @@ -89143,9 +87444,14 @@ module.exports = class kuna extends acx { }; side = this.safeString (sideMap, side, side); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_id'); const id = this.safeString (trade, 'id'); return { @@ -89165,29 +87471,6 @@ module.exports = class kuna extends acx { }; } - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); - } - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.privateGetTradesMy (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const trades = await this.fetchTrades (symbol, since, limit, params); @@ -89206,15 +87489,210 @@ module.exports = class kuna extends acx { } return result; } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + const response = await this.privateGetMembersMe (params); + const balances = this.safeValue (response, 'accounts'); + const result = { 'info': balances }; + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'market': this.marketId (symbol), + 'side': side, + 'volume': amount.toString (), + 'ord_type': type, + }; + if (type === 'limit') { + request['price'] = price.toString (); + } + const response = await this.privatePostOrders (this.extend (request, params)); + const marketId = this.safeValue (response, 'market'); + const market = this.safeValue (this.markets_by_id, marketId); + return this.parseOrder (response, market); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': id, + }; + const response = await this.privatePostOrderDelete (this.extend (request, params)); + const order = this.parseOrder (response); + const status = order['status']; + if (status === 'closed' || status === 'canceled') { + throw new OrderNotFound (this.id + ' ' + this.json (order)); + } + return order; + } + + parseOrderStatus (status) { + const statuses = { + 'done': 'closed', + 'wait': 'open', + 'cancel': 'canceled', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + const marketId = this.safeString (order, 'market'); + const symbol = this.safeSymbol (marketId, market); + const timestamp = this.parse8601 (this.safeString (order, 'created_at')); + const status = this.parseOrderStatus (this.safeString (order, 'state')); + const type = this.safeString (order, 'type'); + const side = this.safeString (order, 'side'); + const id = this.safeString (order, 'id'); + return this.safeOrder ({ + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': undefined, + 'status': status, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': this.safeNumber (order, 'price'), + 'stopPrice': undefined, + 'amount': this.safeNumber (order, 'volume'), + 'filled': this.safeNumber (order, 'executed_volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'trades': undefined, + 'fee': undefined, + 'info': order, + 'cost': undefined, + 'average': undefined, + }); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': parseInt (id), + }; + const response = await this.privateGetOrder (this.extend (request, params)); + return this.parseOrder (response); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetOrders (this.extend (request, params)); + // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder + // with order cache + fetchOpenOrders + // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX + return this.parseOrders (response, market, since, limit); + } + + async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetTradesMy (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); + } + + nonce () { + return this.milliseconds (); + } + + encodeParams (params) { + if ('orders' in params) { + const orders = params['orders']; + let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); + for (let i = 0; i < orders.length; i++) { + const order = orders[i]; + const keys = Object.keys (order); + for (let k = 0; k < keys.length; k++) { + const key = keys[k]; + const value = order[key]; + query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); + } + } + return query; + } + return this.urlencode (this.keysort (params)); + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let request = '/api/' + this.version + '/' + this.implodeParams (path, params); + if ('extension' in this.urls) { + request += this.urls['extension']; + } + const query = this.omit (params, this.extractParams (path)); + let url = this.urls['api'] + request; + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const nonce = this.nonce ().toString (); + const query = this.encodeParams (this.extend ({ + 'access_key': this.apiKey, + 'tonce': nonce, + }, params)); + const auth = method + '|' + request + '|' + query; + const signed = this.hmac (this.encode (auth), this.encode (this.secret)); + const suffix = query + '&signature=' + signed; + if (method === 'GET') { + url += '?' + suffix; + } else { + body = suffix; + headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; + } + } + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; + } + if (code === 400) { + const error = this.safeValue (response, 'error'); + const errorCode = this.safeString (error, 'code'); + const feedback = this.id + ' ' + this.json (response); + this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); + // fallback to default error handler + } + } }; -},{"./acx.js":4,"./base/errors":8}],105:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],102:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89323,10 +87801,10 @@ module.exports = class lakebtc extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -89344,16 +87822,16 @@ module.exports = class lakebtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -89363,7 +87841,7 @@ module.exports = class lakebtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -89394,14 +87872,11 @@ module.exports = class lakebtc extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -89538,14 +88013,14 @@ module.exports = class lakebtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],106:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],103:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, DDoSProtection, BadRequest, AuthenticationError } = require ('./base/errors'); -const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89626,6 +88101,7 @@ module.exports = class latoken extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.1 / 100, @@ -89710,7 +88186,7 @@ module.exports = class latoken extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minQty'), + 'min': this.safeNumber (market, 'minQty'), 'max': undefined, }, 'price': { @@ -89760,7 +88236,7 @@ module.exports = class latoken extends Exchange { const numericId = this.safeInteger (currency, 'currencyId'); const code = this.safeCurrencyCode (id); const precision = this.safeInteger (currency, 'precission'); - const fee = this.safeFloat (currency, 'fee'); + const fee = this.safeNumber (currency, 'fee'); const active = undefined; result[code] = { 'id': id, @@ -89794,27 +88270,6 @@ module.exports = class latoken extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const response = await this.privateGetAccountBalances (params); @@ -89838,17 +88293,15 @@ module.exports = class latoken extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const frozen = this.safeFloat (balance, 'frozen'); - const pending = this.safeFloat (balance, 'pending'); - const used = this.sum (frozen, pending); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': used, - 'total': this.safeFloat (balance, 'amount'), - }; + const frozen = this.safeString (balance, 'frozen'); + const pending = this.safeString (balance, 'pending'); + const account = this.account (); + account['used'] = Precise.stringAdd (frozen, pending); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -89893,20 +88346,20 @@ module.exports = class latoken extends Exchange { // const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; if (open !== undefined && close !== undefined) { change = close - open; } - const percentage = this.safeFloat (ticker, 'priceChange'); + const percentage = this.safeNumber (ticker, 'priceChange'); const timestamp = this.nonce (); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'low': this.safeFloat (ticker, 'low'), - 'high': this.safeFloat (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -89920,7 +88373,7 @@ module.exports = class latoken extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -90004,22 +88457,19 @@ module.exports = class latoken extends Exchange { timestamp *= 1000; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'orderId'); - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -90154,29 +88604,17 @@ module.exports = class latoken extends Exchange { const symbol = this.safeSymbol (marketId, market); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executedAmount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executedAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderStatus')); - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const timeFilled = this.safeTimestamp (order, 'timeFilled'); let lastTradeTimestamp = undefined; if ((timeFilled !== undefined) && (timeFilled > 0)) { lastTradeTimestamp = timeFilled; } const clientOrderId = this.safeString (order, 'cliOrdId'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -90191,14 +88629,14 @@ module.exports = class latoken extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'average': undefined, - 'remaining': remaining, + 'remaining': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -90428,13 +88866,14 @@ module.exports = class latoken extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],107:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],104:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -90632,8 +89071,8 @@ module.exports = class lbank extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const info = ticker; ticker = info['ticker']; - const last = this.safeFloat (ticker, 'latest'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'latest'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; if (percentage !== undefined) { const relativeChange = this.sum (1, percentage / 100); @@ -90654,8 +89093,8 @@ module.exports = class lbank extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -90668,8 +89107,8 @@ module.exports = class lbank extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'turnover'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'turnover'), 'info': info, }; } @@ -90719,17 +89158,15 @@ module.exports = class lbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (trade, 'date_ms'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'tid'); const type = undefined; - const side = this.safeString (trade, 'type'); + let side = this.safeString (trade, 'type'); + side = side.replace ('_market', ''); return { 'id': id, 'info': this.safeValue (trade, 'info', trade), @@ -90777,11 +89214,11 @@ module.exports = class lbank extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -90846,12 +89283,12 @@ module.exports = class lbank extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (freeze, currencyId); - account['total'] = this.safeFloat (asset, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (freeze, currencyId); + account['total'] = this.safeString (asset, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -90879,35 +89316,20 @@ module.exports = class lbank extends Exchange { // "status":2 // } // - let symbol = undefined; - const responseMarket = this.safeValue (this.marketsById, order['symbol']); - if (responseMarket !== undefined) { - symbol = responseMarket['symbol']; - } else if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeInteger (order, 'create_time'); // Limit Order Request Returns: Order Price // Market Order Returns: cny amount of market order - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount', 0.0); - const filled = this.safeFloat (order, 'deal_amount', 0.0); - const av_price = this.safeFloat (order, 'avg_price'); - let cost = undefined; - if (av_price !== undefined) { - cost = filled * av_price; - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount', 0.0); + const filled = this.safeNumber (order, 'deal_amount', 0.0); + const average = this.safeNumber (order, 'avg_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'order_id'); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -90921,15 +89343,15 @@ module.exports = class lbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': this.safeValue (order, 'info', order), - 'average': undefined, - }; + 'average': average, + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -91129,14 +89551,15 @@ module.exports = class lbank extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],108:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],105:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported } = require ('./base/errors'); +const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -91240,7 +89663,7 @@ module.exports = class liquid extends Exchange { 'trading': { 'tierBased': true, 'percentage': true, - 'taker': 0.0015, + 'taker': 0.0030, 'maker': 0.0000, 'tiers': { 'perpetual': { @@ -91259,48 +89682,52 @@ module.exports = class liquid extends Exchange { [ 300000000, -0.00025 ], ], 'taker': [ - [ 0, 0.000600 ], - [ 25000, 0.000575 ], - [ 50000, 0.000550 ], - [ 100000, 0.000525 ], - [ 1000000, 0.000500 ], - [ 10000000, 0.000475 ], - [ 25000000, 0.000450 ], - [ 50000000, 0.000425 ], - [ 75000000, 0.000400 ], - [ 100000000, 0.000375 ], - [ 200000000, 0.000350 ], - [ 300000000, 0.000325 ], + [ 0, 0.00120 ], + [ 25000, 0.00115 ], + [ 50000, 0.00110 ], + [ 100000, 0.00105 ], + [ 1000000, 0.00100 ], + [ 10000000, 0.00095 ], + [ 25000000, 0.00090 ], + [ 50000000, 0.00085 ], + [ 75000000, 0.00080 ], + [ 100000000, 0.00075 ], + [ 200000000, 0.00070 ], + [ 300000000, 0.00065 ], ], }, 'spot': { 'taker': [ - [ 0, 0.0015 ], - [ 10000, 0.0015 ], - [ 20000, 0.0014 ], - [ 50000, 0.0013 ], - [ 100000, 0.0010 ], - [ 1000000, 0.0008 ], - [ 5000000, 0.0006 ], - [ 10000000, 0.0005 ], - [ 25000000, 0.0005 ], - [ 50000000, 0.00045 ], - [ 100000000, 0.0004 ], - [ 200000000, 0.0003 ], + [ 0, 0.003 ], + [ 10000, 0.0029 ], + [ 20000, 0.0028 ], + [ 50000, 0.0026 ], + [ 100000, 0.0020 ], + [ 1000000, 0.0016 ], + [ 5000000, 0.0012 ], + [ 10000000, 0.0010 ], + [ 25000000, 0.0009 ], + [ 50000000, 0.0008 ], + [ 100000000, 0.0007 ], + [ 200000000, 0.0006 ], + [ 500000000, 0.0004 ], + [ 1000000000, 0.0003 ], ], 'maker': [ [ 0, 0.0000 ], - [ 10000, 0.0015 ], - [ 20000, 0.1400 ], - [ 50000, 0.1300 ], - [ 100000, 0.0800 ], - [ 1000000, 0.0004 ], - [ 5000000, 0.00035 ], - [ 10000000, 0.00025 ], + [ 10000, 0.0020 ], + [ 20000, 0.0019 ], + [ 50000, 0.0018 ], + [ 100000, 0.0016 ], + [ 1000000, 0.0008 ], + [ 5000000, 0.0007 ], + [ 10000000, 0.0005 ], [ 25000000, 0.0000 ], [ 50000000, 0.0000 ], [ 100000000, 0.0000 ], [ 200000000, 0.0000 ], + [ 500000000, 0.0000 ], + [ 1000000000, 0.0000 ], ], }, }, @@ -91319,6 +89746,7 @@ module.exports = class liquid extends Exchange { 'less_than_order_size': InvalidOrder, 'price_too_high': InvalidOrder, 'price_too_small': InvalidOrder, // {"errors":{"order":["price_too_small"]}} + 'product_disabled': BadSymbol, // {"errors":{"order":["product_disabled"]}} }, 'commonCurrencies': { 'WIN': 'WCOIN', @@ -91368,7 +89796,7 @@ module.exports = class liquid extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': decimalPrecision, 'limits': { 'amount': { @@ -91384,7 +89812,7 @@ module.exports = class liquid extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal'), + 'min': this.safeNumber (currency, 'minimum_withdrawal'), 'max': undefined, }, }, @@ -91509,19 +89937,19 @@ module.exports = class liquid extends Exchange { let maker = this.fees['trading']['maker']; let taker = this.fees['trading']['taker']; if (type === 'swap') { - maker = this.safeFloat (market, 'maker_fee', this.fees['trading']['maker']); - taker = this.safeFloat (market, 'taker_fee', this.fees['trading']['taker']); + maker = this.safeNumber (market, 'maker_fee', this.fees['trading']['maker']); + taker = this.safeNumber (market, 'taker_fee', this.fees['trading']['taker']); } const disabled = this.safeValue (market, 'disabled', false); const active = !disabled; const baseCurrency = this.safeValue (currenciesByCode, base); const precision = { 'amount': 0.00000001, - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; let minAmount = undefined; if (baseCurrency !== undefined) { - minAmount = this.safeFloat (baseCurrency['info'], 'minimum_order_quantity'); + minAmount = this.safeNumber (baseCurrency['info'], 'minimum_order_quantity'); } const limits = { 'amount': { @@ -91603,8 +90031,8 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } for (let i = 0; i < fiat.length; i++) { @@ -91612,11 +90040,11 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -91635,7 +90063,7 @@ module.exports = class liquid extends Exchange { if (ticker['last_traded_price']) { const length = ticker['last_traded_price'].length; if (length > 0) { - last = this.safeFloat (ticker, 'last_traded_price'); + last = this.safeNumber (ticker, 'last_traded_price'); } } } @@ -91660,7 +90088,7 @@ module.exports = class liquid extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'last_price_24h'); + const open = this.safeNumber (ticker, 'last_price_24h'); if (open !== undefined && last !== undefined) { change = last - open; average = this.sum (last, open) / 2; @@ -91672,11 +90100,11 @@ module.exports = class liquid extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_market_ask'), - 'low': this.safeFloat (ticker, 'low_market_bid'), - 'bid': this.safeFloat (ticker, 'market_bid'), + 'high': this.safeNumber (ticker, 'high_market_ask'), + 'low': this.safeNumber (ticker, 'low_market_bid'), + 'bid': this.safeNumber (ticker, 'market_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'market_ask'), + 'ask': this.safeNumber (ticker, 'market_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -91686,7 +90114,7 @@ module.exports = class liquid extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'volume_24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -91732,14 +90160,11 @@ module.exports = class liquid extends Exchange { if (mySide !== undefined) { takerOrMaker = (takerSide === mySide) ? 'taker' : 'maker'; } - let cost = undefined; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -91942,9 +90367,9 @@ module.exports = class liquid extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeValue (this.markets_by_id, marketId); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'filled_quantity'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + let filled = this.safeNumber (order, 'filled_quantity'); + const price = this.safeNumber (order, 'price'); let symbol = undefined; let feeCurrency = undefined; if (market !== undefined) { @@ -91954,7 +90379,7 @@ module.exports = class liquid extends Exchange { const type = this.safeString (order, 'order_type'); let tradeCost = 0; let tradeFilled = 0; - let average = this.safeFloat (order, 'average_price'); + let average = this.safeNumber (order, 'average_price'); const trades = this.parseTrades (this.safeValue (order, 'executions', []), market, undefined, undefined, { 'order': orderId, 'type': type, @@ -92011,7 +90436,7 @@ module.exports = class liquid extends Exchange { 'trades': trades, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'order_fee'), + 'cost': this.safeNumber (order, 'order_fee'), }, 'info': order, }; @@ -92166,7 +90591,7 @@ module.exports = class liquid extends Exchange { const updated = this.safeTimestamp (transaction, 'updated_at'); const type = 'withdrawal'; const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); return { 'info': transaction, 'id': id, @@ -92267,13 +90692,14 @@ module.exports = class liquid extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],109:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],106:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -92349,6 +90775,10 @@ module.exports = class luno extends Exchange { 'quotes/{id}', 'withdrawals', 'withdrawals/{id}', + 'transfers', + // GET /api/exchange/2/listorders + // GET /api/exchange/2/orders/{id} + // GET /api/exchange/3/order ], 'post': [ 'accounts', @@ -92423,12 +90853,12 @@ module.exports = class luno extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), - 'max': this.safeFloat (market, 'max_volume'), + 'min': this.safeNumber (market, 'min_volume'), + 'max': this.safeNumber (market, 'max_volume'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -92479,20 +90909,22 @@ module.exports = class luno extends Exchange { const wallet = wallets[i]; const currencyId = this.safeString (wallet, 'asset'); const code = this.safeCurrencyCode (currencyId); - const reserved = this.safeFloat (wallet, 'reserved'); - const unconfirmed = this.safeFloat (wallet, 'unconfirmed'); - const balance = this.safeFloat (wallet, 'balance'); + const reserved = this.safeString (wallet, 'reserved'); + const unconfirmed = this.safeString (wallet, 'unconfirmed'); + const balance = this.safeString (wallet, 'balance'); + const reservedUnconfirmed = Precise.stringAdd (reserved, unconfirmed); + const balanceUnconfirmed = Precise.stringAdd (balance, unconfirmed); if (code in result) { - result[code]['used'] = this.sum (result[code]['used'], reserved, unconfirmed); - result[code]['total'] = this.sum (result[code]['total'], balance, unconfirmed); + result[code]['used'] = Precise.stringAdd (result[code]['used'], reservedUnconfirmed); + result[code]['total'] = Precise.stringAdd (result[code]['total'], balanceUnconfirmed); } else { const account = this.account (); - account['used'] = this.sum (reserved, unconfirmed); - account['total'] = this.sum (balance, unconfirmed); + account['used'] = reservedUnconfirmed; + account['total'] = balanceUnconfirmed; result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -92543,18 +90975,12 @@ module.exports = class luno extends Exchange { const side = (order['type'] === 'ASK') ? 'sell' : 'buy'; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'limit_volume'); - const quoteFee = this.safeFloat (order, 'fee_counter'); - const baseFee = this.safeFloat (order, 'fee_base'); - const filled = this.safeFloat (order, 'base'); - const cost = this.safeFloat (order, 'counter'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'limit_volume'); + const quoteFee = this.safeNumber (order, 'fee_counter'); + const baseFee = this.safeNumber (order, 'fee_base'); + const filled = this.safeNumber (order, 'base'); + const cost = this.safeNumber (order, 'counter'); const fee = { 'currency': undefined }; if (quoteFee) { fee['cost'] = quoteFee; @@ -92568,7 +90994,7 @@ module.exports = class luno extends Exchange { } } const id = this.safeString (order, 'order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -92585,12 +91011,12 @@ module.exports = class luno extends Exchange { 'amount': amount, 'filled': filled, 'cost': cost, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -92636,16 +91062,16 @@ module.exports = class luno extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -92655,7 +91081,7 @@ module.exports = class luno extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'rolling_24_hour_volume'), + 'baseVolume': this.safeNumber (ticker, 'rolling_24_hour_volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -92706,8 +91132,8 @@ module.exports = class luno extends Exchange { } else { side = trade['is_buy'] ? 'buy' : 'sell'; } - const feeBase = this.safeFloat (trade, 'fee_base'); - const feeCounter = this.safeFloat (trade, 'fee_counter'); + const feeBase = this.safeNumber (trade, 'fee_base'); + const feeCounter = this.safeNumber (trade, 'fee_counter'); let feeCurrency = undefined; let feeCost = undefined; if (feeBase !== undefined) { @@ -92732,10 +91158,10 @@ module.exports = class luno extends Exchange { 'type': undefined, 'side': side, 'takerOrMaker': takerOrMaker, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), // Does not include potential fee costs - 'cost': this.safeFloat (trade, 'counter'), + 'cost': this.safeNumber (trade, 'counter'), 'fee': { 'cost': feeCost, 'currency': feeCurrency, @@ -92782,8 +91208,8 @@ module.exports = class luno extends Exchange { const response = await this.privateGetFeeInfo (params); return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } @@ -92917,9 +91343,9 @@ module.exports = class luno extends Exchange { const timestamp = this.safeValue (entry, 'timestamp'); const currencyId = this.safeString (entry, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - const available_delta = this.safeFloat (entry, 'available_delta'); - const balance_delta = this.safeFloat (entry, 'balance_delta'); - const after = this.safeFloat (entry, 'balance'); + const available_delta = this.safeNumber (entry, 'available_delta'); + const balance_delta = this.safeNumber (entry, 'balance_delta'); + const after = this.safeNumber (entry, 'balance'); const comment = this.safeString (entry, 'description'); let before = after; let amount = 0.0; @@ -92988,12 +91414,13 @@ module.exports = class luno extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],110:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],107:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -93175,18 +91602,16 @@ module.exports = class lykke extends Exchange { const id = this.safeString2 (trade, 'id', 'Id'); const orderId = this.safeString (trade, 'OrderId'); const timestamp = this.parse8601 (this.safeString2 (trade, 'dateTime', 'DateTime')); - const price = this.safeFloat2 (trade, 'price', 'Price'); - let amount = this.safeFloat2 (trade, 'volume', 'Amount'); + const priceString = this.safeString2 (trade, 'price', 'Price'); + let amountString = this.safeString2 (trade, 'volume', 'Amount'); let side = this.safeStringLower (trade, 'action'); if (side === undefined) { - if (amount < 0) { - side = 'sell'; - } else { - side = 'buy'; - } + side = (amountString[0] === '-') ? 'sell' : 'buy'; } - amount = Math.abs (amount); - const cost = price * amount; + amountString = (amountString[0] === '-') ? amountString.slice (1) : amountString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = { 'cost': 0, // There are no fees for trading. https://www.lykke.com/wallet-fees-and-limits/ 'currency': market['quote'], @@ -93247,11 +91672,11 @@ module.exports = class lykke extends Exchange { const currencyId = this.safeString (balance, 'AssetId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Balance'); - account['used'] = this.safeFloat (balance, 'Reserved'); + account['total'] = this.safeString (balance, 'Balance'); + account['used'] = this.safeString (balance, 'Reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -93298,7 +91723,7 @@ module.exports = class lykke extends Exchange { // } // const id = this.safeString (result, 'Id'); - price = this.safeFloat (result, 'Price'); + price = this.safeNumber (result, 'Price'); return { 'id': id, 'info': result, @@ -93389,16 +91814,16 @@ module.exports = class lykke extends Exchange { if (market) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'lastPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -93409,7 +91834,7 @@ module.exports = class lykke extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume24H'), + 'quoteVolume': this.safeNumber (ticker, 'volume24H'), 'info': ticker, }; } @@ -93467,20 +91892,18 @@ module.exports = class lykke extends Exchange { } else if (('CreatedAt' in order) && (order['CreatedAt'])) { timestamp = this.parse8601 (order['CreatedAt']); } - const price = this.safeFloat (order, 'Price'); + const price = this.safeNumber (order, 'Price'); let side = undefined; - let amount = this.safeFloat (order, 'Volume'); + let amount = this.safeNumber (order, 'Volume'); if (amount < 0) { side = 'sell'; amount = Math.abs (amount); } else { side = 'buy'; } - const remaining = Math.abs (this.safeFloat (order, 'RemainingVolume')); - const filled = amount - remaining; - const cost = filled * price; + const remaining = Math.abs (this.safeNumber (order, 'RemainingVolume')); const id = this.safeString (order, 'Id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -93494,15 +91917,15 @@ module.exports = class lykke extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -93563,8 +91986,8 @@ module.exports = class lykke extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - let amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + let amount = this.safeNumber (bidask, amountKey); if (amount < 0) { amount = -amount; } @@ -93604,13 +92027,14 @@ module.exports = class lykke extends Exchange { } }; -},{"./base/Exchange":6}],111:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7}],108:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -93767,7 +92191,7 @@ module.exports = class mercado extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, baseId), + 'min': this.safeNumber (amountLimits, baseId), 'max': undefined, }, 'price': { @@ -93803,16 +92227,16 @@ module.exports = class mercado extends Exchange { const response = await this.publicGetCoinTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'ticker', {}); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -93822,7 +92246,7 @@ module.exports = class mercado extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -93837,15 +92261,12 @@ module.exports = class mercado extends Exchange { const id = this.safeString2 (trade, 'tid', 'operation_id'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee_rate'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee_rate'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -93902,12 +92323,12 @@ module.exports = class mercado extends Exchange { if (currencyId in balances) { const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -94014,32 +92435,31 @@ module.exports = class mercado extends Exchange { // } // const id = this.safeString (order, 'order_id'); + const order_type = this.safeString (order, 'order_type'); let side = undefined; if ('order_type' in order) { - side = (order['order_type'] === 1) ? 'buy' : 'sell'; + side = (order_type === '1') ? 'buy' : 'sell'; } const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'coin_pair'); market = this.safeMarket (marketId, market); const timestamp = this.safeTimestamp (order, 'created_timestamp'); const fee = { - 'cost': this.safeFloat (order, 'fee'), + 'cost': this.safeNumber (order, 'fee'), 'currency': market['quote'], }; - const price = this.safeFloat (order, 'limit_price'); - // price = this.safeFloat (order, 'executed_price_avg', price); - const average = this.safeFloat (order, 'executed_price_avg'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'executed_quantity'); - const remaining = amount - filled; - const cost = filled * average; + const price = this.safeNumber (order, 'limit_price'); + // price = this.safeNumber (order, 'executed_price_avg', price); + const average = this.safeNumber (order, 'executed_price_avg'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const lastTradeTimestamp = this.safeTimestamp (order, 'updated_timestamp'); const rawTrades = this.safeValue (order, 'operations', []); const trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'side': side, 'order': id, }); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -94053,15 +92473,15 @@ module.exports = class mercado extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -94119,11 +92539,11 @@ module.exports = class mercado extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -94244,13 +92664,14 @@ module.exports = class mercado extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],112:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],109:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -94319,11 +92740,11 @@ module.exports = class mixcoins extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.safeFloat (balance, 'lock'); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = this.safeString (balance, 'lock'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -94343,16 +92764,16 @@ module.exports = class mixcoins extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'result'); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -94362,7 +92783,7 @@ module.exports = class mixcoins extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -94375,14 +92796,11 @@ module.exports = class mixcoins extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -94475,7 +92893,7 @@ module.exports = class mixcoins extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],113:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],110:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -94483,6 +92901,7 @@ module.exports = class mixcoins extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -94722,7 +93141,7 @@ module.exports = class ndax extends Exchange { const name = this.safeString (currency, 'ProductFullName'); const type = this.safeString (currency, 'ProductType'); const code = this.safeCurrencyCode (this.safeString (currency, 'Product')); - const precision = this.safeFloat (currency, 'TickSize'); + const precision = this.safeNumber (currency, 'TickSize'); const isDisabled = this.safeValue (currency, 'IsDisabled'); const active = !isDisabled; result[code] = { @@ -94803,8 +93222,8 @@ module.exports = class ndax extends Exchange { const quote = this.safeCurrencyCode (this.safeString (market, 'Product2Symbol')); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'QuantityIncrement'), - 'price': this.safeFloat (market, 'PriceIncrement'), + 'amount': this.safeNumber (market, 'QuantityIncrement'), + 'price': this.safeNumber (market, 'PriceIncrement'), }; const sessionStatus = this.safeString (market, 'SessionStatus'); const isDisable = this.safeValue (market, 'IsDisable'); @@ -94822,11 +93241,11 @@ module.exports = class ndax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinimumQuantity'), + 'min': this.safeNumber (market, 'MinimumQuantity'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'MinimumPrice'), + 'min': this.safeNumber (market, 'MinimumPrice'), 'max': undefined, }, 'cost': { @@ -94947,27 +93366,27 @@ module.exports = class ndax extends Exchange { const timestamp = this.safeInteger (ticker, 'TimeStamp'); const marketId = this.safeString (ticker, 'InstrumentId'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'LastTradedPx'); - const percentage = this.safeFloat (ticker, 'Rolling24HrPxChangePercent'); - const change = this.safeFloat (ticker, 'Rolling24HrPxChange'); - const open = this.safeFloat (ticker, 'SessionOpen'); + const last = this.safeNumber (ticker, 'LastTradedPx'); + const percentage = this.safeNumber (ticker, 'Rolling24HrPxChangePercent'); + const change = this.safeNumber (ticker, 'Rolling24HrPxChange'); + const open = this.safeNumber (ticker, 'SessionOpen'); let average = undefined; if ((last !== undefined) && (change !== undefined)) { average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'Rolling24HrVolume'); - const quoteVolume = this.safeFloat (ticker, 'Rolling24HrNotional'); + const baseVolume = this.safeNumber (ticker, 'Rolling24HrVolume'); + const quoteVolume = this.safeNumber (ticker, 'Rolling24HrNotional'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'SessionHigh'), - 'low': this.safeFloat (ticker, 'SessionLow'), - 'bid': this.safeFloat (ticker, 'BestBid'), - 'bidVolume': undefined, // this.safeFloat (ticker, 'BidQty'), always shows 0 - 'ask': this.safeFloat (ticker, 'BestOffer'), - 'askVolume': undefined, // this.safeFloat (ticker, 'AskQty'), always shows 0 + 'high': this.safeNumber (ticker, 'SessionHigh'), + 'low': this.safeNumber (ticker, 'SessionLow'), + 'bid': this.safeNumber (ticker, 'BestBid'), + 'bidVolume': undefined, // this.safeNumber (ticker, 'BidQty'), always shows 0 + 'ask': this.safeNumber (ticker, 'BestOffer'), + 'askVolume': undefined, // this.safeNumber (ticker, 'AskQty'), always shows 0 'vwap': vwap, 'open': open, 'close': last, @@ -95040,11 +93459,11 @@ module.exports = class ndax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -95192,8 +93611,8 @@ module.exports = class ndax extends Exchange { // "OMSId":1 // } // - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let cost = undefined; let timestamp = undefined; let id = undefined; @@ -95204,11 +93623,8 @@ module.exports = class ndax extends Exchange { let fee = undefined; let type = undefined; if (Array.isArray (trade)) { - price = this.safeFloat (trade, 3); - amount = this.safeFloat (trade, 2); - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + priceString = this.safeString (trade, 3); + amountString = this.safeString (trade, 2); timestamp = this.safeInteger (trade, 6); id = this.safeString (trade, 0); marketId = this.safeInteger (trade, 1); @@ -95220,13 +93636,13 @@ module.exports = class ndax extends Exchange { id = this.safeString (trade, 'TradeId'); orderId = this.safeString2 (trade, 'OrderId', 'OrigOrderId'); marketId = this.safeString2 (trade, 'InstrumentId', 'Instrument'); - price = this.safeFloat (trade, 'Price'); - amount = this.safeFloat (trade, 'Quantity'); - cost = this.safeFloat2 (trade, 'Value', 'GrossValueExecuted'); + priceString = this.safeString (trade, 'Price'); + amountString = this.safeString (trade, 'Quantity'); + cost = this.safeNumber2 (trade, 'Value', 'GrossValueExecuted'); takerOrMaker = this.safeStringLower (trade, 'MakerTaker'); side = this.safeStringLower (trade, 'Side'); type = this.safeStringLower (trade, 'OrderType'); - const feeCost = this.safeFloat (trade, 'Fee'); + const feeCost = this.safeNumber (trade, 'Fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'FeeProductId'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -95236,6 +93652,11 @@ module.exports = class ndax extends Exchange { }; } } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const symbol = this.safeSymbol (marketId, market); return { 'info': trade, @@ -95350,11 +93771,11 @@ module.exports = class ndax extends Exchange { const currencyId = this.safeString (balance, 'ProductId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Amount'); - account['used'] = this.safeFloat (balance, 'Hold'); + account['total'] = this.safeString (balance, 'Amount'); + account['used'] = this.safeString (balance, 'Hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseLedgerEntryType (type) { @@ -95400,8 +93821,8 @@ module.exports = class ndax extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'ReferenceType')); const currencyId = this.safeString (item, 'ProductId'); const code = this.safeCurrencyCode (currencyId, currency); - const credit = this.safeFloat (item, 'CR'); - const debit = this.safeFloat (item, 'DR'); + const credit = this.safeNumber (item, 'CR'); + const debit = this.safeNumber (item, 'DR'); let amount = undefined; let direction = undefined; if (credit > 0) { @@ -95413,7 +93834,7 @@ module.exports = class ndax extends Exchange { } const timestamp = this.safeInteger (item, 'TimeStamp'); let before = undefined; - const after = this.safeFloat (item, 'Balance'); + const after = this.safeNumber (item, 'Balance'); if (direction === 'out') { before = this.sum (after, amount); } else if (direction === 'in') { @@ -95561,36 +93982,26 @@ module.exports = class ndax extends Exchange { // const id = this.safeString2 (order, 'ReplacementOrderId', 'OrderId'); const timestamp = this.safeInteger (order, 'ReceiveTime'); - let lastTradeTimestamp = undefined; + const lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); const marketId = this.safeString (order, 'Instrument'); const symbol = this.safeSymbol (marketId, market); const side = this.safeStringLower (order, 'Side'); const type = this.safeStringLower (order, 'OrderType'); const clientOrderId = this.safeString2 (order, 'ReplacementClOrdId', 'ClientOrderId'); - let price = this.safeFloat (order, 'Price', 0.0); + let price = this.safeNumber (order, 'Price', 0.0); price = (price > 0.0) ? price : undefined; - const amount = this.safeFloat (order, 'OrigQuantity'); - const filled = this.safeFloat (order, 'QuantityExecuted'); - const cost = this.safeFloat (order, 'GrossValueExecuted'); - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (filled > 0) { - lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); - average = this.safeFloat (order, 'AvgPrice', 0.0); - average = (average > 0) ? average : undefined; - } - } - let stopPrice = this.safeFloat (order, 'StopPrice', 0.0); + const amount = this.safeNumber (order, 'OrigQuantity'); + const filled = this.safeNumber (order, 'QuantityExecuted'); + const cost = this.safeNumber (order, 'GrossValueExecuted'); + let average = this.safeNumber (order, 'AvgPrice', 0.0); + average = (average > 0) ? average : undefined; + let stopPrice = this.safeNumber (order, 'StopPrice', 0.0); stopPrice = (stopPrice > 0.0) ? stopPrice : undefined; const timeInForce = undefined; const status = this.parseOrderStatus (this.safeString (order, 'OrderState')); const fee = undefined; const trades = undefined; - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -95609,10 +94020,10 @@ module.exports = class ndax extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -96410,8 +94821,8 @@ module.exports = class ndax extends Exchange { } const addressTo = address; const status = this.parseTransactionStatusByType (this.safeString (transaction, 'TicketStatus'), type); - const amount = this.safeFloat (transaction, 'Amount'); - const feeCost = this.safeFloat (transaction, 'FeeAmount'); + const amount = this.safeNumber (transaction, 'Amount'); + const feeCost = this.safeNumber (transaction, 'FeeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -96492,7 +94903,7 @@ module.exports = class ndax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],114:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],111:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -96500,6 +94911,7 @@ module.exports = class ndax extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, BadRequest, CancelPending, OrderNotFound, InsufficientFunds, RateLimitExceeded, InvalidOrder, AccountSuspended, BadSymbol, OnMaintenance } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -96692,7 +95104,7 @@ module.exports = class novadax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -96700,7 +95112,7 @@ module.exports = class novadax extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderValue'), + 'min': this.safeNumber (market, 'minOrderValue'), 'max': undefined, }, }; @@ -96742,8 +95154,8 @@ module.exports = class novadax extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const open = this.safeFloat (ticker, 'open24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'open24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let percentage = undefined; let change = undefined; let average = undefined; @@ -96752,18 +95164,18 @@ module.exports = class novadax extends Exchange { percentage = change / open * 100; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'baseVolume24h'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume24h'); + const baseVolume = this.safeNumber (ticker, 'baseVolume24h'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -96919,11 +95331,13 @@ module.exports = class novadax extends Exchange { const orderId = this.safeString (trade, 'orderId'); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeStringLower (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - cost = amount * price; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'volume'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); @@ -96935,7 +95349,7 @@ module.exports = class novadax extends Exchange { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { - 'cost': this.safeFloat (parts, 0), + 'cost': this.safeNumber (parts, 0), 'currency': feeCurrencyCode, }; } @@ -97043,11 +95457,11 @@ module.exports = class novadax extends Exchange { const volumeField = this.safeString (options, 'volume', 'amount'); // or vol return [ this.safeTimestamp (ohlcv, 'score'), - this.safeFloat (ohlcv, 'openPrice'), - this.safeFloat (ohlcv, 'highPrice'), - this.safeFloat (ohlcv, 'lowPrice'), - this.safeFloat (ohlcv, 'closePrice'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'openPrice'), + this.safeNumber (ohlcv, 'highPrice'), + this.safeNumber (ohlcv, 'lowPrice'), + this.safeNumber (ohlcv, 'closePrice'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -97075,12 +95489,12 @@ module.exports = class novadax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'available'); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); + account['total'] = this.safeString (balance, 'available'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -97103,7 +95517,7 @@ module.exports = class novadax extends Exchange { if (uppercaseSide === 'SELL') { request['amount'] = this.amountToPrecision (symbol, amount); } else if (uppercaseSide === 'BUY') { - let value = this.safeFloat (params, 'value'); + let value = this.safeNumber (params, 'value'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -97333,21 +95747,17 @@ module.exports = class novadax extends Exchange { // } // const id = this.safeString (order, 'id'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'filledValue'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'filledValue'); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeInteger (order, 'timestamp'); - const average = this.safeFloat (order, 'averagePrice'); - const filled = this.safeFloat (order, 'filledAmount'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } + const average = this.safeNumber (order, 'averagePrice'); + const filled = this.safeNumber (order, 'filledAmount'); let fee = undefined; - const feeCost = this.safeFloat (order, 'filledFee'); + const feeCost = this.safeNumber (order, 'filledFee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -97356,7 +95766,7 @@ module.exports = class novadax extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -97374,11 +95784,11 @@ module.exports = class novadax extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async withdraw (code, amount, address, tag = undefined, params = {}) { @@ -97541,7 +95951,7 @@ module.exports = class novadax extends Exchange { } else if (type === 'COIN_OUT') { type = 'withdraw'; } - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'addressTag'); const txid = this.safeString (transaction, 'txHash'); @@ -97683,7 +96093,7 @@ module.exports = class novadax extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],115:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],112:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -97833,10 +96243,10 @@ module.exports = class oceanex extends Exchange { 'active': true, 'info': market, 'precision': { - 'amount': this.safeValue (market, 'amount_precision'), - 'price': this.safeValue (market, 'price_precision'), - 'base': this.safeValue (market, 'ask_precision'), - 'quote': this.safeValue (market, 'bid_precision'), + 'amount': this.safeInteger (market, 'amount_precision'), + 'price': this.safeInteger (market, 'price_precision'), + 'base': this.safeInteger (market, 'ask_precision'), + 'quote': this.safeInteger (market, 'bid_precision'), }, 'limits': { 'amount': { @@ -97848,7 +96258,7 @@ module.exports = class oceanex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeValue (market, 'minimum_trading_amount'), + 'min': this.safeNumber (market, 'minimum_trading_amount'), 'max': undefined, }, }, @@ -97942,21 +96352,21 @@ module.exports = class oceanex extends Exchange { 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (ticker, 'last'), - 'last': this.safeFloat (ticker, 'last'), + 'close': this.safeNumber (ticker, 'last'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -98081,8 +96491,8 @@ module.exports = class oceanex extends Exchange { 'type': 'limit', 'takerOrMaker': undefined, 'side': side, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), 'cost': undefined, 'fee': undefined, }; @@ -98109,8 +96519,8 @@ module.exports = class oceanex extends Exchange { result[symbol] = { 'info': group, 'symbol': symbol, - 'maker': this.safeFloat (maker, 'value'), - 'taker': this.safeFloat (taker, 'value'), + 'maker': this.safeNumber (maker, 'value'), + 'taker': this.safeNumber (taker, 'value'), }; } return result; @@ -98132,11 +96542,11 @@ module.exports = class oceanex extends Exchange { const currencyId = this.safeValue (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -98244,12 +96654,12 @@ module.exports = class oceanex extends Exchange { // const status = this.parseOrderStatus (this.safeValue (order, 'state')); const marketId = this.safeString2 (order, 'market', 'market_id'); - const symbol = this.safeSymbol (marketId); + const symbol = this.safeSymbol (marketId, market); let timestamp = this.safeTimestamp (order, 'created_on'); if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'created_at')); } - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, @@ -98261,17 +96671,17 @@ module.exports = class oceanex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeValue (order, 'side'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_price'), - 'amount': this.safeFloat (order, 'volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'filled': this.safeFloat (order, 'executed_volume'), + 'average': this.safeNumber (order, 'avg_price'), + 'amount': this.safeNumber (order, 'volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'filled': this.safeNumber (order, 'executed_volume'), 'status': status, 'cost': undefined, 'trades': undefined, 'fee': undefined, - }; + }); } parseOrderStatus (status) { @@ -98364,12 +96774,12 @@ module.exports = class oceanex extends Exchange { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['codes'], errorCode, feedback); this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - throw new ExchangeError (response); + throw new ExchangeError (feedback); } } }; -},{"./base/Exchange":6,"./base/errors":8}],116:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],113:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -98406,7 +96816,7 @@ module.exports = class okcoin extends okex { } }; -},{"./okex.js":117}],117:[function(require,module,exports){ +},{"./okex.js":114}],114:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -98414,6 +96824,7 @@ module.exports = class okcoin extends okex { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -99207,7 +97618,7 @@ module.exports = class okex extends Exchange { let option = false; let baseId = this.safeString (market, 'base_currency'); let quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { if ('option_type' in market) { marketType = 'option'; @@ -99233,12 +97644,12 @@ module.exports = class okex extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = spot ? (base + '/' + quote) : id; - const lotSize = this.safeFloat2 (market, 'lot_size', 'trade_increment'); + const lotSize = this.safeNumber2 (market, 'lot_size', 'trade_increment'); const precision = { - 'amount': this.safeFloat (market, 'size_increment', lotSize), - 'price': this.safeFloat (market, 'tick_size'), + 'amount': this.safeNumber (market, 'size_increment', lotSize), + 'price': this.safeNumber (market, 'tick_size'), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const active = true; const fees = this.safeValue2 (this.fees, marketType, 'trading', {}); return this.extend (fees, { @@ -99413,7 +97824,7 @@ module.exports = class okex extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal'), + 'min': this.safeNumber (currency, 'min_withdrawal'), 'max': undefined, }, }, @@ -99488,18 +97899,18 @@ module.exports = class okex extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open_24h'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open_24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_24h'), - 'low': this.safeFloat (ticker, 'low_24h'), - 'bid': this.safeFloat (ticker, 'best_bid'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (ticker, 'best_ask'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber (ticker, 'high_24h'), + 'low': this.safeNumber (ticker, 'low_24h'), + 'bid': this.safeNumber (ticker, 'best_bid'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (ticker, 'best_ask'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': undefined, 'open': open, 'close': last, @@ -99508,8 +97919,8 @@ module.exports = class okex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'base_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'quote_volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'base_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'quote_volume_24h'), 'info': ticker, }; } @@ -99646,9 +98057,12 @@ module.exports = class okex extends Exchange { quote = market['quote']; } const timestamp = this.parse8601 (this.safeString2 (trade, 'timestamp', 'created_at')); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'size', 'qty'); - amount = this.safeFloat (trade, 'order_qty', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'size', 'qty'); + amountString = this.safeString (trade, 'order_qty', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -99656,13 +98070,7 @@ module.exports = class okex extends Exchange { takerOrMaker = 'taker'; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -99771,22 +98179,22 @@ module.exports = class okex extends Exchange { } return [ timestamp, // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets ]; } else { return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, 'volume'), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, 'volume'), // Base Volume ]; } } @@ -99932,9 +98340,9 @@ module.exports = class okex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeNumber (balance, 'balance'); + account['used'] = this.safeNumber (balance, 'hold'); + account['free'] = this.safeNumber (balance, 'available'); result[code] = account; } return this.parseBalance (result); @@ -100004,9 +98412,9 @@ module.exports = class okex extends Exchange { const currencyId = parts[1]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (marketBalance, 'balance'); - account['used'] = this.safeFloat (marketBalance, 'hold'); - account['free'] = this.safeFloat (marketBalance, 'available'); + account['total'] = this.safeNumber (marketBalance, 'balance'); + account['used'] = this.safeNumber (marketBalance, 'hold'); + account['free'] = this.safeNumber (marketBalance, 'available'); accounts[code] = account; } else { throw new NotSupported (this.id + ' margin balance response format has changed!'); @@ -100059,29 +98467,29 @@ module.exports = class okex extends Exchange { const code = this.safeCurrencyCode (id); const balance = this.safeValue (info, id, {}); const account = this.account (); - const totalAvailBalance = this.safeFloat (balance, 'total_avail_balance'); + const totalAvailBalance = this.safeNumber (balance, 'total_avail_balance'); if (this.safeString (balance, 'margin_mode') === 'fixed') { const contracts = this.safeValue (balance, 'contracts', []); let free = totalAvailBalance; for (let i = 0; i < contracts.length; i++) { const contract = contracts[i]; - const fixedBalance = this.safeFloat (contract, 'fixed_balance'); - const realizedPnl = this.safeFloat (contract, 'realized_pnl'); - const marginFrozen = this.safeFloat (contract, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (contract, 'margin_for_unfilled'); + const fixedBalance = this.safeNumber (contract, 'fixed_balance'); + const realizedPnl = this.safeNumber (contract, 'realized_pnl'); + const marginFrozen = this.safeNumber (contract, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (contract, 'margin_for_unfilled'); const margin = this.sum (fixedBalance, realizedPnl) - marginFrozen - marginForUnfilled; free = this.sum (free, margin); } account['free'] = free; } else { - const realizedPnl = this.safeFloat (balance, 'realized_pnl'); - const unrealizedPnl = this.safeFloat (balance, 'unrealized_pnl'); - const marginFrozen = this.safeFloat (balance, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (balance, 'margin_for_unfilled'); + const realizedPnl = this.safeNumber (balance, 'realized_pnl'); + const unrealizedPnl = this.safeNumber (balance, 'unrealized_pnl'); + const marginFrozen = this.safeNumber (balance, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (balance, 'margin_for_unfilled'); account['free'] = this.sum (totalAvailBalance, realizedPnl, unrealizedPnl) - marginFrozen - marginForUnfilled; } // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); + account['total'] = this.safeNumber (balance, 'equity'); result[code] = account; } return this.parseBalance (result); @@ -100119,8 +98527,8 @@ module.exports = class okex extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeNumber (balance, 'equity'); + account['free'] = this.safeNumber (balance, 'total_avail_balance'); result[symbol] = account; } return this.parseBalance (result); @@ -100324,7 +98732,7 @@ module.exports = class okex extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -100534,8 +98942,8 @@ module.exports = class okex extends Exchange { symbol = market['symbol']; } } - let amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat2 (order, 'filled_size', 'filled_qty'); + let amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber2 (order, 'filled_size', 'filled_qty'); let remaining = undefined; if (amount !== undefined) { if (filled !== undefined) { @@ -100546,9 +98954,9 @@ module.exports = class okex extends Exchange { if (type === 'market') { remaining = 0; } - let cost = this.safeFloat2 (order, 'filled_notional', 'funds'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); + let cost = this.safeNumber2 (order, 'filled_notional', 'funds'); + const price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'price_avg'); if (cost === undefined) { if (filled !== undefined && average !== undefined) { cost = average * filled; @@ -100559,7 +98967,7 @@ module.exports = class okex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'state')); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -100572,7 +98980,7 @@ module.exports = class okex extends Exchange { if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) { clientOrderId = undefined; // fix empty clientOrderId string } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); return { 'info': order, 'id': id, @@ -100816,16 +99224,6 @@ module.exports = class okex extends Exchange { return await this.fetchOrdersByState ('7', symbol, since, limit, params); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -100853,7 +99251,8 @@ module.exports = class okex extends Exchange { async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); - const currency = this.currency (code); + const parts = code.split ('-'); + const currency = this.currency (parts[0]); const request = { 'currency': currency['id'], }; @@ -100866,8 +99265,8 @@ module.exports = class okex extends Exchange { // } // ] // - const addresses = this.parseDepositAddresses (response); - const address = this.safeValue (addresses, code); + const addressesByCode = this.parseDepositAddresses (response); + const address = this.safeValue (addressesByCode, code); if (address === undefined) { throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first'); } @@ -101042,7 +99441,7 @@ module.exports = class okex extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const txid = this.safeString (transaction, 'txid'); const timestamp = this.parse8601 (this.safeString (transaction, 'timestamp')); @@ -101105,19 +99504,19 @@ module.exports = class okex extends Exchange { let feeCurrencyId = undefined; if (receivedCurrencyId === quoteId) { side = this.safeString (otherTrade, 'side'); - amount = this.safeFloat (otherTrade, 'size'); - cost = this.safeFloat (userTrade, 'size'); + amount = this.safeNumber (otherTrade, 'size'); + cost = this.safeNumber (userTrade, 'size'); feeCurrencyId = this.safeString (otherTrade, 'currency'); } else { side = this.safeString (userTrade, 'side'); - amount = this.safeFloat (userTrade, 'size'); - cost = this.safeFloat (otherTrade, 'size'); + amount = this.safeNumber (userTrade, 'size'); + cost = this.safeNumber (otherTrade, 'size'); feeCurrencyId = this.safeString (userTrade, 'currency'); } const id = this.safeString (userTrade, 'trade_id'); - const price = this.safeFloat (userTrade, 'price'); - const feeCostFirst = this.safeFloat (otherTrade, 'fee'); - const feeCostSecond = this.safeFloat (userTrade, 'fee'); + const price = this.safeNumber (userTrade, 'price'); + const feeCostFirst = this.safeNumber (otherTrade, 'fee'); + const feeCostSecond = this.safeNumber (userTrade, 'fee'); const feeCurrencyCodeFirst = this.safeCurrencyCode (this.safeString (otherTrade, 'currency')); const feeCurrencyCodeSecond = this.safeCurrencyCode (this.safeString (userTrade, 'currency')); let fee = undefined; @@ -101549,7 +99948,7 @@ module.exports = class okex extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); let method = undefined; const defaultType = this.safeString2 (this.options, 'fetchPositions', 'defaultType'); @@ -101931,14 +100330,14 @@ module.exports = class okex extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'timestamp')); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; const marketId = this.safeString (item, 'instrument_id'); let symbol = undefined; @@ -102048,13 +100447,14 @@ module.exports = class okex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],118:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],115:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -102147,12 +100547,12 @@ module.exports = class paymium extends Exchange { if (free in response) { const account = this.account (); const used = 'locked_' + currencyId; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -102171,30 +100571,30 @@ module.exports = class paymium extends Exchange { }; const ticker = await this.publicGetDataCurrencyTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'at'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'price'); + const last = this.safeNumber (ticker, 'price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'variation'), + 'percentage': this.safeNumber (ticker, 'variation'), 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, @@ -102210,15 +100610,12 @@ module.exports = class paymium extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); + const priceString = this.safeString (trade, 'price'); const amountField = 'traded_' + market['base'].toLowerCase (); - const amount = this.safeFloat (trade, amountField); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const amountString = this.safeString (trade, amountField); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -102313,7 +100710,7 @@ module.exports = class paymium extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],119:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],116:[function(require,module,exports){ 'use strict'; // ---------------------------------------------------------------------------- @@ -102621,13 +101018,13 @@ module.exports = class phemex extends Exchange { }); } - parseSafeFloat (value = undefined) { + parseSafeNumber (value = undefined) { if (value === undefined) { return value; } value = value.replace (',', ''); const parts = value.split (' '); - return this.safeFloat (parts, 0); + return this.safeNumber (parts, 0); } parseSwapMarket (market) { @@ -102651,7 +101048,9 @@ module.exports = class phemex extends Exchange { // "minPriceEp":5000, // "maxPriceEp":10000000000, // "maxOrderQty":1000000, - // "type":"Perpetual" + // "type":"Perpetual", + // "status":"Listed", + // "tipOrderQty":1000000, // "steps":"50", // "riskLimits":[ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000}, @@ -102676,7 +101075,7 @@ module.exports = class phemex extends Exchange { // } // const id = this.safeString (market, 'symbol'); - const baseId = this.safeString (market, 'baseCurrency', 'contractUnderlyingAssets'); + const baseId = this.safeString2 (market, 'baseCurrency', 'contractUnderlyingAssets'); const quoteId = this.safeString (market, 'quoteCurrency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); @@ -102693,16 +101092,16 @@ module.exports = class phemex extends Exchange { } const linear = !inverse; const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const priceScale = this.safeInteger (market, 'priceScale'); const ratioScale = this.safeInteger (market, 'ratioScale'); const valueScale = this.safeInteger (market, 'valueScale'); - const minPriceEp = this.safeFloat (market, 'minPriceEp'); - const maxPriceEp = this.safeFloat (market, 'maxPriceEp'); - const makerFeeRateEr = this.safeFloat (market, 'makerFeeRateEr'); - const takerFeeRateEr = this.safeFloat (market, 'takerFeeRateEr'); + const minPriceEp = this.safeNumber (market, 'minPriceEp'); + const maxPriceEp = this.safeNumber (market, 'maxPriceEp'); + const makerFeeRateEr = this.safeNumber (market, 'makerFeeRateEr'); + const takerFeeRateEr = this.safeNumber (market, 'takerFeeRateEr'); if (makerFeeRateEr !== undefined) { maker = this.fromEn (makerFeeRateEr, ratioScale, 0.00000001); } @@ -102720,10 +101119,11 @@ module.exports = class phemex extends Exchange { }, 'cost': { 'min': undefined, - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderQty')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderQty')), }, }; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -102772,7 +101172,9 @@ module.exports = class phemex extends Exchange { // "defaultMakerFee":"0.001", // "defaultMakerFeeEr":100000, // "baseQtyPrecision":6, - // "quoteQtyPrecision":2 + // "quoteQtyPrecision":2, + // "status":"Listed", + // "tipOrderQty":20 // } // const type = this.safeStringLower (market, 'type'); @@ -102783,30 +101185,31 @@ module.exports = class phemex extends Exchange { const inverse = undefined; const spot = true; const swap = false; - const taker = this.safeFloat (market, 'defaultTakerFee'); - const maker = this.safeFloat (market, 'defaultMakerFee'); + const taker = this.safeNumber (market, 'defaultTakerFee'); + const maker = this.safeNumber (market, 'defaultMakerFee'); const precision = { - 'amount': this.parseSafeFloat (this.safeString (market, 'baseTickSize')), - 'price': this.parseSafeFloat (this.safeString (market, 'quoteTickSize')), + 'amount': this.parseSafeNumber (this.safeString (market, 'baseTickSize')), + 'price': this.parseSafeNumber (this.safeString (market, 'quoteTickSize')), }; const limits = { 'amount': { 'min': precision['amount'], - 'max': this.parseSafeFloat (this.safeString (market, 'maxBaseOrderSize')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxBaseOrderSize')), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.parseSafeFloat (this.safeString (market, 'minOrderValue')), - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderValue')), + 'min': this.parseSafeNumber (this.safeString (market, 'minOrderValue')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderValue')), }, }; const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -102996,8 +101399,8 @@ module.exports = class phemex extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const valueScale = this.safeInteger (currency, 'valueScale'); - const minValueEv = this.safeFloat (currency, 'minValueEv'); - const maxValueEv = this.safeFloat (currency, 'maxValueEv'); + const minValueEv = this.safeNumber (currency, 'minValueEv'); + const maxValueEv = this.safeNumber (currency, 'maxValueEv'); let minAmount = undefined; let maxAmount = undefined; let precision = undefined; @@ -103047,12 +101450,12 @@ module.exports = class phemex extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - let amount = this.safeFloat (bidask, amountKey); + let amount = this.safeNumber (bidask, amountKey); if (market['spot']) { amount = this.fromEv (amount, market); } return [ - this.fromEp (this.safeFloat (bidask, priceKey), market), + this.fromEp (this.safeNumber (bidask, priceKey), market), amount, ]; } @@ -103186,16 +101589,16 @@ module.exports = class phemex extends Exchange { // let baseVolume = undefined; if ((market !== undefined) && market['spot']) { - baseVolume = this.fromEv (this.safeFloat (ohlcv, 7), market); + baseVolume = this.fromEv (this.safeNumber (ohlcv, 7), market); } else { baseVolume = this.safeInteger (ohlcv, 7); } return [ this.safeTimestamp (ohlcv, 0), - this.fromEp (this.safeFloat (ohlcv, 3), market), - this.fromEp (this.safeFloat (ohlcv, 4), market), - this.fromEp (this.safeFloat (ohlcv, 5), market), - this.fromEp (this.safeFloat (ohlcv, 6), market), + this.fromEp (this.safeNumber (ohlcv, 3), market), + this.fromEp (this.safeNumber (ohlcv, 4), market), + this.fromEp (this.safeNumber (ohlcv, 5), market), + this.fromEp (this.safeNumber (ohlcv, 6), market), baseVolume, ]; } @@ -103288,11 +101691,11 @@ module.exports = class phemex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.000001); - const last = this.fromEp (this.safeFloat (ticker, 'lastEp'), market); - const quoteVolume = this.fromEp (this.safeFloat (ticker, 'turnoverEv'), market); - let baseVolume = this.safeFloat (ticker, 'volume'); + const last = this.fromEp (this.safeNumber (ticker, 'lastEp'), market); + const quoteVolume = this.fromEp (this.safeNumber (ticker, 'turnoverEv'), market); + let baseVolume = this.safeNumber (ticker, 'volume'); if (baseVolume === undefined) { - baseVolume = this.fromEv (this.safeFloat (ticker, 'volumeEv')); + baseVolume = this.fromEv (this.safeNumber (ticker, 'volumeEv')); } let vwap = undefined; if ((market !== undefined) && (market['spot'])) { @@ -103301,7 +101704,7 @@ module.exports = class phemex extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.fromEp (this.safeFloat (ticker, 'openEp'), market); + const open = this.fromEp (this.safeNumber (ticker, 'openEp'), market); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -103313,11 +101716,11 @@ module.exports = class phemex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.fromEp (this.safeFloat (ticker, 'highEp'), market), - 'low': this.fromEp (this.safeFloat (ticker, 'lowEp'), market), - 'bid': this.fromEp (this.safeFloat (ticker, 'bidEp'), market), + 'high': this.fromEp (this.safeNumber (ticker, 'highEp'), market), + 'low': this.fromEp (this.safeNumber (ticker, 'lowEp'), market), + 'bid': this.fromEp (this.safeNumber (ticker, 'bidEp'), market), 'bidVolume': undefined, - 'ask': this.fromEp (this.safeFloat (ticker, 'askEp'), market), + 'ask': this.fromEp (this.safeNumber (ticker, 'askEp'), market), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -103508,8 +101911,8 @@ module.exports = class phemex extends Exchange { id = this.safeString (trade, tradeLength - 4); } side = this.safeStringLower (trade, tradeLength - 3); - price = this.fromEp (this.safeFloat (trade, tradeLength - 2), market); - amount = this.fromEv (this.safeFloat (trade, tradeLength - 1), market); + price = this.fromEp (this.safeNumber (trade, tradeLength - 2), market); + amount = this.fromEv (this.safeNumber (trade, tradeLength - 1), market); if (market['spot']) { if ((price !== undefined) && (amount !== undefined)) { cost = price * amount; @@ -103525,14 +101928,14 @@ module.exports = class phemex extends Exchange { if (execStatus === 'MakerFill') { takerOrMaker = 'maker'; } - price = this.fromEp (this.safeFloat (trade, 'execPriceEp'), market); - amount = this.fromEv (this.safeFloat (trade, 'execBaseQtyEv'), market); - amount = this.safeFloat (trade, 'execQty', amount); - cost = this.fromEv (this.safeFloat2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); - const feeCost = this.fromEv (this.safeFloat (trade, 'execFeeEv'), market); + price = this.fromEp (this.safeNumber (trade, 'execPriceEp'), market); + amount = this.fromEv (this.safeNumber (trade, 'execBaseQtyEv'), market); + amount = this.safeNumber (trade, 'execQty', amount); + cost = this.fromEv (this.safeNumber2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); + const feeCost = this.fromEv (this.safeNumber (trade, 'execFeeEv'), market); if (feeCost !== undefined) { let feeRate = undefined; - let feeRateEr = this.safeFloat (trade, 'feeRateEr'); + let feeRateEr = this.safeNumber (trade, 'feeRateEr'); if (feeRateEr < 0) { feeRateEr = Math.abs (feeRateEr); feeRate = this.fromEr (feeRateEr, market); @@ -103608,9 +102011,9 @@ module.exports = class phemex extends Exchange { const currency = this.safeValue (this.currencies, code, {}); const scale = this.safeInteger (currency, 'valueScale', 8); const account = this.account (); - const balanceEv = this.safeFloat (balance, 'balanceEv'); - const lockedTradingBalanceEv = this.safeFloat (balance, 'lockedTradingBalanceEv'); - const lockedWithdrawEv = this.safeFloat (balance, 'lockedWithdrawEv'); + const balanceEv = this.safeNumber (balance, 'balanceEv'); + const lockedTradingBalanceEv = this.safeNumber (balance, 'lockedTradingBalanceEv'); + const lockedWithdrawEv = this.safeNumber (balance, 'lockedWithdrawEv'); const total = this.fromEn (balanceEv, scale, scale, DECIMAL_PLACES); const lockedTradingBalance = this.fromEn (lockedTradingBalanceEv, scale, scale, DECIMAL_PLACES); const lockedWithdraw = this.fromEn (lockedWithdrawEv, scale, scale, DECIMAL_PLACES); @@ -103704,8 +102107,8 @@ module.exports = class phemex extends Exchange { const code = this.safeCurrencyCode (currencyId); const currency = this.currency (code); const account = this.account (); - const accountBalanceEv = this.safeFloat (balance, 'accountBalanceEv'); - const totalUsedBalanceEv = this.safeFloat (balance, 'totalUsedBalanceEv'); + const accountBalanceEv = this.safeNumber (balance, 'accountBalanceEv'); + const totalUsedBalanceEv = this.safeNumber (balance, 'totalUsedBalanceEv'); const valueScale = this.safeInteger (currency, 'valueScale', 8); account['total'] = this.fromEn (accountBalanceEv, valueScale, valueScale, DECIMAL_PLACES); account['used'] = this.fromEn (totalUsedBalanceEv, valueScale, valueScale, DECIMAL_PLACES); @@ -103937,21 +102340,21 @@ module.exports = class phemex extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let price = this.fromEp (this.safeFloat (order, 'priceEp'), market); + let price = this.fromEp (this.safeNumber (order, 'priceEp'), market); if (price === 0) { price = undefined; } - const amount = this.fromEv (this.safeFloat (order, 'baseQtyEv'), market); - const remaining = this.fromEv (this.safeFloat (order, 'leavesBaseQtyEv'), market); - let filled = this.fromEv (this.safeFloat (order, 'cumBaseQtyEv'), market); - const cost = this.fromEv (this.safeFloat (order, 'quoteQtyEv'), market); - const average = this.fromEp (this.safeFloat (order, 'avgPriceEp'), market); + const amount = this.fromEv (this.safeNumber (order, 'baseQtyEv'), market); + const remaining = this.fromEv (this.safeNumber (order, 'leavesBaseQtyEv'), market); + let filled = this.fromEv (this.safeNumber (order, 'cumBaseQtyEv'), market); + const cost = this.fromEv (this.safeNumber (order, 'quoteQtyEv'), market); + const average = this.fromEp (this.safeNumber (order, 'avgPriceEp'), market); const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'ordType')); const timestamp = this.safeIntegerProduct2 (order, 'actionTimeNs', 'createTimeNs', 0.000001); let fee = undefined; - const feeCost = this.fromEv (this.safeFloat (order, 'cumFeeEv'), market); + const feeCost = this.fromEv (this.safeNumber (order, 'cumFeeEv'), market); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -103964,7 +102367,7 @@ module.exports = class phemex extends Exchange { } } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.fromEp (this.safeFloat (order, 'stopPxEp', market)); + const stopPrice = this.fromEp (this.safeNumber (order, 'stopPxEp', market)); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -104037,18 +102440,18 @@ module.exports = class phemex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'orderType')); - const price = this.fromEp (this.safeFloat (order, 'priceEp'), market); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); + const price = this.fromEp (this.safeNumber (order, 'priceEp'), market); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); const timestamp = this.safeIntegerProduct (order, 'actionTimeNs', 0.000001); - const cost = this.safeFloat (order, 'cumValue'); + const cost = this.safeNumber (order, 'cumValue'); let lastTradeTimestamp = this.safeIntegerProduct (order, 'transactTimeNs', 0.000001); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -104123,7 +102526,7 @@ module.exports = class phemex extends Exchange { } request['qtyType'] = qtyType; if (qtyType === 'ByQuote') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); params = this.omit (params, 'cost'); if (this.options['createOrderByQuoteRequiresPrice']) { if (price !== undefined) { @@ -104143,7 +102546,7 @@ module.exports = class phemex extends Exchange { if (type === 'Limit') { request['priceEp'] = this.toEp (price, market); } - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice !== undefined) { request['stopPxEp'] = this.toEp (stopPrice, market); } @@ -104651,7 +103054,7 @@ module.exports = class phemex extends Exchange { const code = currency['code']; const timestamp = this.safeInteger2 (transaction, 'createdAt', 'submitedAt'); let type = this.safeStringLower (transaction, 'type'); - const feeCost = this.fromEn (this.safeFloat (transaction, 'feeEv'), currency['valueScale'], currency['precision']); + const feeCost = this.fromEn (this.safeNumber (transaction, 'feeEv'), currency['valueScale'], currency['precision']); let fee = undefined; if (feeCost !== undefined) { type = 'withdrawal'; @@ -104661,7 +103064,7 @@ module.exports = class phemex extends Exchange { }; } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.fromEn (this.safeFloat (transaction, 'amountEv'), currency['valueScale'], currency['precision']); + const amount = this.fromEn (this.safeNumber (transaction, 'amountEv'), currency['valueScale'], currency['precision']); return { 'info': transaction, 'id': id, @@ -104683,7 +103086,7 @@ module.exports = class phemex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.safeString (params, 'code'); const request = {}; @@ -104836,13 +103239,14 @@ module.exports = class phemex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],120:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],117:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -104952,6 +103356,7 @@ module.exports = class poloniex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', // starting from Jan 8 2020 'maker': 0.0009, 'taker': 0.0009, @@ -105046,24 +103451,6 @@ module.exports = class poloniex extends Exchange { }); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - parseOHLCV (ohlcv, market = undefined) { // // { @@ -105079,11 +103466,11 @@ module.exports = class poloniex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'date'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'quoteVolume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'quoteVolume'), ]; } @@ -105176,11 +103563,11 @@ module.exports = class poloniex extends Exchange { const balance = this.safeValue (response, currencyId, {}); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onOrders'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFees (params = {}) { @@ -105198,8 +103585,8 @@ module.exports = class poloniex extends Exchange { // return { 'info': fees, - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), 'withdraw': {}, 'deposit': {}, }; @@ -105257,8 +103644,8 @@ module.exports = class poloniex extends Exchange { let open = undefined; let change = undefined; let average = undefined; - const last = this.safeFloat (ticker, 'last'); - const relativeChange = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const relativeChange = this.safeNumber (ticker, 'percentChange'); if (relativeChange !== -1) { open = last / this.sum (1, relativeChange); change = last - open; @@ -105268,11 +103655,11 @@ module.exports = class poloniex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24hr'), - 'low': this.safeFloat (ticker, 'low24hr'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high24hr'), + 'low': this.safeNumber (ticker, 'low24hr'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -105282,8 +103669,8 @@ module.exports = class poloniex extends Exchange { 'change': change, 'percentage': relativeChange * 100, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -105324,7 +103711,7 @@ module.exports = class poloniex extends Exchange { const code = this.safeCurrencyCode (id); const active = (currency['delisted'] === 0) && !currency['disabled']; const numericId = this.safeInteger (currency, 'id'); - const fee = this.safeFloat (currency, 'txFee'); + const fee = this.safeNumber (currency, 'txFee'); result[code] = { 'id': id, 'numericId': numericId, @@ -105415,13 +103802,18 @@ module.exports = class poloniex extends Exchange { } const side = this.safeString (trade, 'type'); let fee = undefined; - const price = this.safeFloat (trade, 'rate'); - const cost = this.safeFloat (trade, 'total'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const feeDisplay = this.safeString (trade, 'feeDisplay'); if (feeDisplay !== undefined) { const parts = feeDisplay.split (' '); - const feeCost = this.safeFloat (parts, 0); + const feeCost = this.safeNumber (parts, 0); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -105440,7 +103832,7 @@ module.exports = class poloniex extends Exchange { } } let takerOrMaker = undefined; - const takerAdjustment = this.safeFloat (trade, 'takerAdjustment'); + const takerAdjustment = this.safeNumber (trade, 'takerAdjustment'); if (takerAdjustment !== undefined) { takerOrMaker = 'taker'; } @@ -105686,9 +104078,9 @@ module.exports = class poloniex extends Exchange { if (resultingTrades !== undefined) { trades = this.parseTrades (resultingTrades, market); } - const price = this.safeFloat2 (order, 'price', 'rate'); - let remaining = this.safeFloat (order, 'amount'); - let amount = this.safeFloat (order, 'startingAmount'); + const price = this.safeNumber2 (order, 'price', 'rate'); + let remaining = this.safeNumber (order, 'amount'); + let amount = this.safeNumber (order, 'startingAmount'); let filled = undefined; let cost = 0; if (amount !== undefined) { @@ -105738,7 +104130,7 @@ module.exports = class poloniex extends Exchange { } const id = this.safeString (order, 'orderNumber'); let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -106235,11 +104627,11 @@ module.exports = class poloniex extends Exchange { const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit'; const type = this.safeString (transaction, 'type', defaultType); const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'paymentID'); // according to https://poloniex.com/fees/ - const feeCost = this.safeFloat (transaction, 'fee', 0); + const feeCost = this.safeNumber (transaction, 'fee', 0); if (type === 'withdrawal') { // poloniex withdrawal amount includes the fee amount = amount - feeCost; @@ -106323,7 +104715,7 @@ module.exports = class poloniex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],121:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],118:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -106331,6 +104723,7 @@ module.exports = class poloniex extends Exchange { const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, BadResponse, BadRequest, InvalidOrder, InsufficientFunds, AuthenticationError, ArgumentsRequired, InvalidAddress, RateLimitExceeded, DDoSProtection, BadSymbol } = require ('./base/errors'); const { TRUNCATE, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -106466,9 +104859,11 @@ module.exports = class probit extends Exchange { }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', 'CBC': 'CryptoBharatCoin', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'HBC': 'Hybrid Bank Cash', 'UNI': 'UNICORN Token', }, @@ -106517,11 +104912,11 @@ module.exports = class probit extends Exchange { const costPrecision = this.safeInteger (market, 'cost_precision'); const precision = { 'amount': 1 / Math.pow (10, amountPrecision), - 'price': this.safeFloat (market, 'price_increment'), + 'price': this.safeNumber (market, 'price_increment'), 'cost': 1 / Math.pow (10, costPrecision), }; - const takerFeeRate = this.safeFloat (market, 'taker_fee_rate'); - const makerFeeRate = this.safeFloat (market, 'maker_fee_rate'); + const takerFeeRate = this.safeNumber (market, 'taker_fee_rate'); + const makerFeeRate = this.safeNumber (market, 'maker_fee_rate'); result.push ({ 'id': id, 'info': market, @@ -106536,16 +104931,16 @@ module.exports = class probit extends Exchange { 'maker': makerFeeRate / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_cost'), - 'max': this.safeFloat (market, 'max_cost'), + 'min': this.safeNumber (market, 'min_cost'), + 'max': this.safeNumber (market, 'max_cost'), }, }, }); @@ -106632,7 +105027,7 @@ module.exports = class probit extends Exchange { // [ { 'amount': '0.015', 'priority': 1, 'currency_id': 'ETH' }, {} ] for (let j = 0; j < withdrawalFees.length; j++) { const withdrawalFee = withdrawalFees[j]; - const amount = this.safeFloat (withdrawalFee, 'amount'); + const amount = this.safeNumber (withdrawalFee, 'amount'); const priority = this.safeInteger (withdrawalFee, 'priority'); if ((amount !== undefined) && (priority !== undefined)) { fees.push (withdrawalFee); @@ -106640,7 +105035,7 @@ module.exports = class probit extends Exchange { } const withdrawalFeesByPriority = this.sortBy (fees, 'priority'); const withdrawalFee = this.safeValue (withdrawalFeesByPriority, 0, {}); - const fee = this.safeFloat (withdrawalFee, 'amount'); + const fee = this.safeNumber (withdrawalFee, 'amount'); result[code] = { 'id': id, 'code': code, @@ -106663,11 +105058,11 @@ module.exports = class probit extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (platform, 'min_deposit_amount'), + 'min': this.safeNumber (platform, 'min_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (platform, 'min_withdrawal_amount'), + 'min': this.safeNumber (platform, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -106697,11 +105092,11 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (balance, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'total'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -106753,14 +105148,6 @@ module.exports = class probit extends Exchange { return this.parseTickers (data, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -106808,8 +105195,8 @@ module.exports = class probit extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); - const close = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); + const close = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); let percentage = undefined; let open = undefined; if (change !== undefined) { @@ -106818,15 +105205,15 @@ module.exports = class probit extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -106968,16 +105355,13 @@ module.exports = class probit extends Exchange { marketId = this.safeString (trade, 'market_id', marketId); const symbol = this.safeSymbol (marketId, market, '-'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'order_id'); - const feeCost = this.safeFloat (trade, 'fee_amount'); + const feeCost = this.safeNumber (trade, 'fee_amount'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency_id'); @@ -107121,11 +105505,11 @@ module.exports = class probit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'start_time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_volume'), ]; } @@ -107224,37 +105608,24 @@ module.exports = class probit extends Exchange { const marketId = this.safeString (order, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'time')); - let price = this.safeFloat (order, 'limit_price'); - const filled = this.safeFloat (order, 'filled_quantity'); - let remaining = this.safeFloat (order, 'open_quantity'); - const canceledAmount = this.safeFloat (order, 'cancelled_quantity'); + let price = this.safeNumber (order, 'limit_price'); + const filled = this.safeNumber (order, 'filled_quantity'); + let remaining = this.safeNumber (order, 'open_quantity'); + const canceledAmount = this.safeNumber (order, 'cancelled_quantity'); if (canceledAmount !== undefined) { remaining = this.sum (remaining, canceledAmount); } - const amount = this.safeFloat (order, 'quantity', this.sum (filled, remaining)); - let cost = this.safeFloat2 (order, 'filled_cost', 'cost'); + const amount = this.safeNumber (order, 'quantity', this.sum (filled, remaining)); + const cost = this.safeNumber2 (order, 'filled_cost', 'cost'); if (type === 'market') { price = undefined; } - let average = undefined; - if (filled !== undefined) { - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if (cost !== undefined) { - if (filled > 0) { - average = cost / filled; - } - } - } let clientOrderId = this.safeString (order, 'client_order_id'); if (clientOrderId === '') { clientOrderId = undefined; } const timeInForce = this.safeStringUpper (order, 'time_in_force'); - return { + return this.safeOrder ({ 'id': id, 'info': order, 'clientOrderId': clientOrderId, @@ -107271,11 +105642,11 @@ module.exports = class probit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'average': average, + 'average': undefined, 'cost': cost, 'fee': undefined, 'trades': undefined, - }; + }); } costToPrecision (symbol, cost) { @@ -107305,7 +105676,7 @@ module.exports = class probit extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -107430,16 +105801,6 @@ module.exports = class probit extends Exchange { return this.parseDepositAddresses (data); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { // In order to use this method // you need to allow API withdrawal from the API Settings Page, and @@ -107470,7 +105831,7 @@ module.exports = class probit extends Exchange { parseTransaction (transaction, currency = undefined) { const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'destination_tag'); const txid = this.safeString (transaction, 'hash'); @@ -107479,7 +105840,7 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (transaction, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined && feeCost !== 0) { fee = { @@ -107609,13 +105970,14 @@ module.exports = class probit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],122:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],119:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -107791,11 +106153,11 @@ module.exports = class qtrade extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_buy_value'), + 'min': this.safeNumber (market, 'minimum_buy_value'), 'max': undefined, }, 'price': { @@ -107876,12 +106238,12 @@ module.exports = class qtrade extends Exchange { 'info': currency, 'type': type, 'name': name, - 'fee': this.safeFloat (config, 'withdraw_fee'), + 'fee': this.safeNumber (config, 'withdraw_fee'), 'precision': this.safeInteger (currency, 'precision'), 'active': active, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimum_order'), + 'min': this.safeNumber (currency, 'minimum_order'), 'max': undefined, }, 'price': { @@ -107916,11 +106278,11 @@ module.exports = class qtrade extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'market_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'market_volume'), ]; } @@ -107982,8 +106344,8 @@ module.exports = class qtrade extends Exchange { const result = []; for (let j = 0; j < prices.length; j++) { const priceAsString = prices[j]; - const price = this.safeFloat (prices, j); - const amount = this.safeFloat (bidasks, priceAsString); + const price = this.safeNumber (prices, j); + const amount = this.safeNumber (bidasks, priceAsString); result.push ([ price, amount ]); } orderbook[side] = result; @@ -108015,12 +106377,12 @@ module.exports = class qtrade extends Exchange { const marketId = this.safeString (ticker, 'id_hr'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeIntegerProduct (ticker, 'last_change', 0.001); - const previous = this.safeFloat (ticker, 'day_open'); - const last = this.safeFloat (ticker, 'last'); - const day_change = this.safeFloat (ticker, 'day_change'); + const previous = this.safeNumber (ticker, 'day_open'); + const last = this.safeNumber (ticker, 'last'); + const day_change = this.safeNumber (ticker, 'day_change'); let percentage = undefined; let change = undefined; - let average = this.safeFloat (ticker, 'day_avg_price'); + let average = this.safeNumber (ticker, 'day_avg_price'); if (day_change !== undefined) { percentage = day_change * 100; if (previous !== undefined) { @@ -108030,18 +106392,18 @@ module.exports = class qtrade extends Exchange { if ((average === undefined) && (last !== undefined) && (previous !== undefined)) { average = this.sum (last, previous) / 2; } - const baseVolume = this.safeFloat (ticker, 'day_volume_market'); - const quoteVolume = this.safeFloat (ticker, 'day_volume_base'); + const baseVolume = this.safeNumber (ticker, 'day_volume_market'); + const quoteVolume = this.safeNumber (ticker, 'day_volume_base'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'day_high'), - 'low': this.safeFloat (ticker, 'day_low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'day_high'), + 'low': this.safeNumber (ticker, 'day_low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': previous, @@ -108249,16 +106611,16 @@ module.exports = class qtrade extends Exchange { const side = this.safeString (trade, 'side'); const marketId = this.safeString (trade, 'market_string'); const symbol = this.safeSymbol (marketId, market, '_'); - let cost = this.safeFloat2 (trade, 'base_volume', 'base_amount'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'market_amount', 'amount'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - if (price !== undefined) { - cost = price * amount; - } + let cost = this.safeNumber2 (trade, 'base_volume', 'base_amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'market_amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'base_fee'); + const feeCost = this.safeNumber (trade, 'base_fee'); if (feeCost !== undefined) { const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; fee = { @@ -108315,7 +106677,7 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); account['used'] = 0; result[code] = account; } @@ -108325,10 +106687,10 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -108457,10 +106819,9 @@ module.exports = class qtrade extends Exchange { side = this.safeString (parts, 0); orderType = this.safeString (parts, 1); } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'market_amount'); - let remaining = this.safeFloat (order, 'market_amount_remaining'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'market_amount'); + const remaining = this.safeNumber (order, 'market_amount_remaining'); const open = this.safeValue (order, 'open', false); const closeReason = this.safeString (order, 'close_reason'); let status = undefined; @@ -108472,58 +106833,21 @@ module.exports = class qtrade extends Exchange { status = 'closed'; } const marketId = this.safeString (order, 'market_string'); - const symbol = this.safeSymbol (marketId, market, '_'); + market = this.safeMarket (marketId, market, '_'); + const symbol = market['symbol']; const rawTrades = this.safeValue (order, 'trades', []); const parsedTrades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id, 'side': side, 'type': orderType, }); - const numTrades = parsedTrades.length; - let lastTradeTimestamp = undefined; - let feeCost = undefined; - let cost = undefined; - if (numTrades > 0) { - feeCost = 0; - cost = 0; - filled = 0; - remaining = amount; - for (let i = 0; i < parsedTrades.length; i++) { - const trade = parsedTrades[i]; - feeCost = this.sum (trade['fee']['cost'], feeCost); - lastTradeTimestamp = this.safeInteger (trade, 'timestamp'); - cost = this.sum (trade['cost'], cost); - filled = this.sum (trade['amount'], filled); - remaining = Math.max (0, remaining - trade['amount']); - } - } - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; - fee = { - 'currency': feeCurrencyCode, - 'cost': feeCost, - }; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let average = undefined; - if (filled !== undefined) { - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': orderType, 'timeInForce': undefined, @@ -108531,15 +106855,16 @@ module.exports = class qtrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, - 'fee': fee, - 'cost': cost, + 'fee': undefined, + 'fees': undefined, + 'cost': undefined, 'trades': parsedTrades, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -109008,7 +107333,7 @@ module.exports = class qtrade extends Exchange { const tagTo = tag; const cancelRequested = this.safeValue (transaction, 'cancel_requested'); const type = (cancelRequested === undefined) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); let status = this.parseTransactionStatus (this.safeString (transaction, 'status')); @@ -109152,7 +107477,7 @@ module.exports = class qtrade extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],123:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],120:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); @@ -109340,8 +107665,8 @@ module.exports = class rightbtc extends Exchange { return result; } - divideSafeFloat (x, key, divisor) { - const value = this.safeFloat (x, key); + divideSafeNumber (x, key, divisor) { + const value = this.safeNumber (x, key); if (value !== undefined) { return value / divisor; } @@ -109351,12 +107676,12 @@ module.exports = class rightbtc extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); - const last = this.divideSafeFloat (ticker, 'last', 1e8); - const high = this.divideSafeFloat (ticker, 'high', 1e8); - const low = this.divideSafeFloat (ticker, 'low', 1e8); - const bid = this.divideSafeFloat (ticker, 'buy', 1e8); - const ask = this.divideSafeFloat (ticker, 'sell', 1e8); - const baseVolume = this.divideSafeFloat (ticker, 'vol24h', 1e8); + const last = this.divideSafeNumber (ticker, 'last', 1e8); + const high = this.divideSafeNumber (ticker, 'high', 1e8); + const low = this.divideSafeNumber (ticker, 'low', 1e8); + const bid = this.divideSafeNumber (ticker, 'buy', 1e8); + const ask = this.divideSafeNumber (ticker, 'sell', 1e8); + const baseVolume = this.divideSafeNumber (ticker, 'vol24h', 1e8); return { 'symbol': symbol, 'timestamp': timestamp, @@ -109460,9 +107785,9 @@ module.exports = class rightbtc extends Exchange { let id = this.safeString (trade, 'tid'); id = this.safeString (trade, 'trade_id', id); const orderId = this.safeString (trade, 'order_id'); - const price = this.divideSafeFloat (trade, 'price', 1e8); - let amount = this.safeFloat (trade, 'amount'); - amount = this.safeFloat (trade, 'quantity', amount); + const price = this.divideSafeNumber (trade, 'price', 1e8); + let amount = this.safeNumber (trade, 'amount'); + amount = this.safeNumber (trade, 'quantity', amount); if (amount !== undefined) { amount = amount / 1e8; } @@ -109559,8 +107884,8 @@ module.exports = class rightbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); // https://github.com/ccxt/ccxt/issues/3873 - account['free'] = this.divideSafeFloat (balance, 'balance', 1e8); - account['used'] = this.divideSafeFloat (balance, 'frozen', 1e8); + account['free'] = this.divideSafeNumber (balance, 'balance', 1e8); + account['used'] = this.divideSafeNumber (balance, 'frozen', 1e8); result[code] = account; } return this.parseBalance (result); @@ -109649,30 +107974,18 @@ module.exports = class rightbtc extends Exchange { } else if ('transactTime' in order) { timestamp = order['transactTime']; } - let price = this.safeFloat2 (order, 'limit', 'price'); + let price = this.safeNumber2 (order, 'limit', 'price'); if (price !== undefined) { price = price / 1e8; } - const amount = this.divideSafeFloat (order, 'quantity', 1e8); - let filled = this.divideSafeFloat (order, 'filled_quantity', 1e8); - let remaining = this.divideSafeFloat (order, 'rest', 1e8); - const cost = this.divideSafeFloat (order, 'cost', 1e8); + const amount = this.divideSafeNumber (order, 'quantity', 1e8); + const filled = this.divideSafeNumber (order, 'filled_quantity', 1e8); + const remaining = this.divideSafeNumber (order, 'rest', 1e8); + const cost = this.divideSafeNumber (order, 'cost', 1e8); // lines 483-494 should be generalized into a base class method - if (amount !== undefined) { - if (remaining === undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - if (filled === undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } - } const type = 'limit'; const side = this.safeStringLower (order, 'side'); - const feeCost = this.divideSafeFloat (order, 'min_fee', 1e8); + const feeCost = this.divideSafeNumber (order, 'min_fee', 1e8); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -109680,13 +107993,13 @@ module.exports = class rightbtc extends Exchange { feeCurrency = market['quote']; } fee = { - 'rate': this.safeFloat (order, 'fee'), + 'rate': this.safeNumber (order, 'fee'), 'cost': feeCost, 'currency': feeCurrency, }; } const trades = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -109708,7 +108021,7 @@ module.exports = class rightbtc extends Exchange { 'fee': fee, 'trades': trades, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -109912,7 +108225,7 @@ module.exports = class rightbtc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],124:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9,"./base/functions/number":15}],121:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -109920,6 +108233,7 @@ module.exports = class rightbtc extends Exchange { const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, BadSymbol, BadRequest, InvalidOrder, ArgumentsRequired, OrderNotFound, InsufficientFunds, DDoSProtection } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110064,12 +108378,12 @@ module.exports = class ripio extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'min_amount'), - 'price': this.safeFloat (market, 'price_tick'), + 'amount': this.safeNumber (market, 'min_amount'), + 'price': this.safeNumber (market, 'price_tick'), }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -110077,15 +108391,15 @@ module.exports = class ripio extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_value'), + 'min': this.safeNumber (market, 'min_value'), 'max': undefined, }, }; const active = this.safeValue (market, 'enabled', true); const fees = this.safeValue (market, 'fees', []); const firstFee = this.safeValue (fees, 0, {}); - const maker = this.safeFloat (firstFee, 'maker_fee', 0.0); - const taker = this.safeFloat (firstFee, 'taker_fee', 0.0); + const maker = this.safeNumber (firstFee, 'maker_fee', 0.0); + const taker = this.safeNumber (firstFee, 'taker_fee', 0.0); result.push ({ 'id': id, 'symbol': symbol, @@ -110192,18 +108506,18 @@ module.exports = class ripio extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); const marketId = this.safeString (ticker, 'pair'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const average = this.safeFloat (ticker, 'avg'); + const last = this.safeNumber (ticker, 'last_price'); + const average = this.safeNumber (ticker, 'avg'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bid_volume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'ask_volume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bid_volume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'ask_volume'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -110345,15 +108659,14 @@ module.exports = class ripio extends Exchange { if (side !== undefined) { side = side.toLowerCase (); } - const price = this.safeFloat2 (trade, 'price', 'match_price'); - const amount = this.safeFloat2 (trade, 'amount', 'exchanged'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString2 (trade, 'price', 'match_price'); + const amountString = this.safeString2 (trade, 'amount', 'exchanged'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'pair'); market = this.safeMarket (marketId, market); - const feeCost = this.safeFloat (trade, takerOrMaker + '_fee'); + const feeCost = this.safeNumber (trade, takerOrMaker + '_fee'); const orderId = this.safeString (trade, takerOrMaker); let fee = undefined; if (feeCost !== undefined) { @@ -110427,11 +108740,11 @@ module.exports = class ripio extends Exchange { const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -110690,16 +109003,16 @@ module.exports = class ripio extends Exchange { // } // const id = this.safeString (order, 'order_id'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat (order, 'notional'); + const amount = this.safeNumber (order, 'amount'); + let cost = this.safeNumber (order, 'notional'); const type = this.safeStringLower (order, 'order_type'); const priceField = (type === 'market') ? 'fill_price' : 'limit_price'; - const price = this.safeFloat (order, priceField); + const price = this.safeNumber (order, priceField); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeTimestamp (order, 'created_at'); let average = this.safeValue (order, 'fill_price'); - let filled = this.safeFloat (order, 'filled'); + let filled = this.safeNumber (order, 'filled'); let remaining = undefined; const fills = this.safeValue (order, 'fills'); let trades = undefined; @@ -110734,7 +109047,7 @@ module.exports = class ripio extends Exchange { } const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); return { 'id': id, 'clientOrderId': undefined, @@ -110860,13 +109173,14 @@ module.exports = class ripio extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],125:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],122:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110977,14 +109291,14 @@ module.exports = class southxchange extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const deposited = this.safeFloat (balance, 'Deposited'); - const unconfirmed = this.safeFloat (balance, 'Unconfirmed'); + const deposited = this.safeString (balance, 'Deposited'); + const unconfirmed = this.safeString (balance, 'Unconfirmed'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'Available'); - account['total'] = this.sum (deposited, unconfirmed); + account['free'] = this.safeString (balance, 'Available'); + account['total'] = Precise.stringAdd (deposited, unconfirmed); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -111002,16 +109316,16 @@ module.exports = class southxchange extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'Last'); + const last = this.safeNumber (ticker, 'Last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'Bid'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -111019,9 +109333,9 @@ module.exports = class southxchange extends Exchange { 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'Variation24Hr'), + 'percentage': this.safeNumber (ticker, 'Variation24Hr'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume24Hr'), + 'baseVolume': this.safeNumber (ticker, 'Volume24Hr'), 'quoteVolume': undefined, 'info': ticker, }; @@ -111055,14 +109369,11 @@ module.exports = class southxchange extends Exchange { parseTrade (trade, market) { const timestamp = this.safeTimestamp (trade, 'At'); - const price = this.safeFloat (trade, 'Price'); - const amount = this.safeFloat (trade, 'Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'Price'); + const amountString = this.safeString (trade, 'Amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'Type'); let symbol = undefined; if (market !== undefined) { @@ -111103,21 +109414,13 @@ module.exports = class southxchange extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const timestamp = undefined; - const price = this.safeFloat (order, 'LimitPrice'); - const amount = this.safeFloat (order, 'OriginalAmount'); - const remaining = this.safeFloat (order, 'Amount'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - cost = price * amount; - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'LimitPrice'); + const amount = this.safeNumber (order, 'OriginalAmount'); + const remaining = this.safeNumber (order, 'Amount'); const type = 'limit'; const side = this.safeStringLower (order, 'Type'); const id = this.safeString (order, 'Code'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -111132,15 +109435,14 @@ module.exports = class southxchange extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'filled': filled, + 'cost': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -111273,8 +109575,8 @@ module.exports = class southxchange extends Exchange { const type = this.safeString (item, 'Type'); const ledgerEntryType = this.parseLedgerEntryType (type); const code = this.safeCurrencyCode (this.safeString (item, 'CurrencyCode'), currency); - let amount = this.safeFloat (item, 'Amount'); - const after = this.safeFloat (item, 'TotalBalance'); + let amount = this.safeNumber (item, 'Amount'); + const after = this.safeNumber (item, 'TotalBalance'); let before = undefined; if (amount !== undefined) { if (after !== undefined) { @@ -111445,7 +109747,7 @@ module.exports = class southxchange extends Exchange { // } // const id = this.safeString (transaction, 'MovementId'); - const amount = this.safeFloat (transaction, 'Amount'); + const amount = this.safeNumber (transaction, 'Amount'); const address = this.safeString (transaction, 'Address'); const addressTo = address; const addressFrom = undefined; @@ -111560,7 +109862,7 @@ module.exports = class southxchange extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],126:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],123:[function(require,module,exports){ (function (module, exports) { 'use strict'; @@ -115088,7 +113390,7 @@ module.exports = class southxchange extends Exchange { }; })(typeof module === 'undefined' || module, this); -},{"buffer":188}],127:[function(require,module,exports){ +},{"buffer":184}],124:[function(require,module,exports){ ;(function (root, factory) { if (typeof exports === "object") { // CommonJS @@ -121077,7 +119379,7 @@ module.exports = class southxchange extends Exchange { return CryptoJS; })); -},{}],128:[function(require,module,exports){ +},{}],125:[function(require,module,exports){ 'use strict'; var elliptic = exports; @@ -121101,7 +119403,7 @@ elliptic.curves = require('./elliptic/curves'); elliptic.ec = require('./elliptic/ec'); elliptic.eddsa = require('./elliptic/eddsa'); -},{"./elliptic/curve":131,"./elliptic/curves":134,"./elliptic/ec":135,"./elliptic/eddsa":138,"./elliptic/utils":142}],129:[function(require,module,exports){ +},{"./elliptic/curve":128,"./elliptic/curves":131,"./elliptic/ec":132,"./elliptic/eddsa":135,"./elliptic/utils":139}],126:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -121478,7 +119780,7 @@ BasePoint.prototype.dblp = function dblp(k) { return r; }; -},{"../../../../BN/bn":126,"../../elliptic":128}],130:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],127:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -121913,7 +120215,7 @@ Point.prototype.eqXToP = function eqXToP(x) { Point.prototype.toP = Point.prototype.normalize; Point.prototype.mixedAdd = Point.prototype.add; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],131:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],128:[function(require,module,exports){ 'use strict'; var curve = exports; @@ -121923,7 +120225,7 @@ curve.short = require('./short'); curve.mont = require('./mont'); curve.edwards = require('./edwards'); -},{"./base":129,"./edwards":130,"./mont":132,"./short":133}],132:[function(require,module,exports){ +},{"./base":126,"./edwards":127,"./mont":129,"./short":130}],129:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -122105,7 +120407,7 @@ Point.prototype.getX = function getX() { return this.x.fromRed(); }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],133:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],130:[function(require,module,exports){ 'use strict'; var curve = require('../curve'); @@ -123045,7 +121347,7 @@ JPoint.prototype.isInfinity = function isInfinity() { return this.z.cmpn(0) === 0; }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../curve":131}],134:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../curve":128}],131:[function(require,module,exports){ 'use strict'; var curves = exports; @@ -123251,7 +121553,7 @@ defineCurve('secp256k1', { ] }); -},{"../elliptic":128,"./precomputed/secp256k1":141}],135:[function(require,module,exports){ +},{"../elliptic":125,"./precomputed/secp256k1":138}],132:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123493,7 +121795,7 @@ EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { throw new Error('Unable to find valid recovery factor'); }; -},{"../../../../BN/bn":126,"../../elliptic":128,"../../hmac-drbg/hmac-drbg":143,"./key":136,"./signature":137}],136:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125,"../../hmac-drbg/hmac-drbg":140,"./key":133,"./signature":134}],133:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123614,7 +121916,7 @@ KeyPair.prototype.inspect = function inspect() { ' pub: ' + (this.pub && this.pub.inspect()) + ' >'; }; -},{"../../../../BN/bn":126,"../../elliptic":128}],137:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],134:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123640,7 +121942,7 @@ function Signature(options, enc) { } module.exports = Signature; -},{"../../../../BN/bn":126,"../../elliptic":128}],138:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../../elliptic":125}],135:[function(require,module,exports){ 'use strict'; var curves = require('../curves'); @@ -123787,7 +122089,7 @@ EDDSA.prototype.isPoint = function isPoint(val) { return val instanceof this.pointClass; }; -},{"../../../../../base/functions/encode":11,"../../../../BN/bn.js":126,"../../../../crypto-js/crypto-js":127,"../curves":134,"../utils":142,"./key":139,"./signature":140}],139:[function(require,module,exports){ +},{"../../../../../base/functions/encode":12,"../../../../BN/bn.js":123,"../../../../crypto-js/crypto-js":124,"../curves":131,"../utils":139,"./key":136,"./signature":137}],136:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -123889,7 +122191,7 @@ KeyPair.prototype.getPublic = function getPublic(enc) { module.exports = KeyPair; -},{"../utils":142}],140:[function(require,module,exports){ +},{"../utils":139}],137:[function(require,module,exports){ 'use strict'; var BN = require('../../../../BN/bn'); @@ -123956,7 +122258,7 @@ Signature.prototype.toHex = function toHex() { module.exports = Signature; -},{"../../../../BN/bn":126,"../utils":142}],141:[function(require,module,exports){ +},{"../../../../BN/bn":123,"../utils":139}],138:[function(require,module,exports){ module.exports = { doubles: { step: 4, @@ -124738,7 +123040,7 @@ module.exports = { } }; -},{}],142:[function(require,module,exports){ +},{}],139:[function(require,module,exports){ 'use strict'; var utils = exports; @@ -124954,7 +123256,7 @@ utils.encode = function encode(arr, enc) { return arr; }; -},{"../../../BN/bn":126}],143:[function(require,module,exports){ +},{"../../../BN/bn":123}],140:[function(require,module,exports){ 'use strict'; var CryptoJS = require('../../../crypto-js/crypto-js'); @@ -125070,7 +123372,7 @@ HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { return utils.wordArrayToBuffer(res); }; -},{"../../../../base/functions/encode":11,"../../../crypto-js/crypto-js":127,"../elliptic/utils":142}],144:[function(require,module,exports){ +},{"../../../../base/functions/encode":12,"../../../crypto-js/crypto-js":124,"../elliptic/utils":139}],141:[function(require,module,exports){ 'use strict'; var fetch = require('../node-fetch/index'); @@ -125111,7 +123413,7 @@ module.exports = function (context) { }; }; -},{"../node-fetch/index":145}],145:[function(require,module,exports){ +},{"../node-fetch/index":142}],142:[function(require,module,exports){ (function (global,Buffer){ 'use strict'; @@ -126679,7 +124981,7 @@ exports.Response = Response; exports.FetchError = FetchError; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"buffer":188,"http":230,"https":193,"stream":229,"url":236,"zlib":187}],146:[function(require,module,exports){ +},{"buffer":184,"http":226,"https":189,"stream":225,"url":232,"zlib":183}],143:[function(require,module,exports){ (function (Buffer){ /*! * RSA library for Node.js @@ -126906,7 +125208,7 @@ module.exports = (function () { })(); }).call(this,require("buffer").Buffer) -},{"./formats/formats.js":153,"./libs/rsa.js":157,"./schemes/schemes.js":159,"./utils":160,"buffer":188}],147:[function(require,module,exports){ +},{"./formats/formats.js":150,"./libs/rsa.js":154,"./schemes/schemes.js":156,"./utils":157,"buffer":184}],144:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. @@ -126921,7 +125223,7 @@ module.exports = { }; -},{}],148:[function(require,module,exports){ +},{}],145:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. var errors = require('./errors'); @@ -126944,7 +125246,7 @@ for (var e in errors) { module.exports[e] = errors[e]; } -},{"./errors":147,"./reader":149,"./types":150}],149:[function(require,module,exports){ +},{"./errors":144,"./reader":146,"./types":147}],146:[function(require,module,exports){ (function (Buffer){ // Copyright 2011 Mark Cavage All rights reserved. @@ -127210,7 +125512,7 @@ Reader.prototype._readTag = function (tag) { module.exports = Reader; }).call(this,require("buffer").Buffer) -},{"./errors":147,"./types":150,"assert":183,"buffer":188}],150:[function(require,module,exports){ +},{"./errors":144,"./types":147,"assert":179,"buffer":184}],147:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. @@ -127248,7 +125550,7 @@ module.exports = { Context: 128 }; -},{}],151:[function(require,module,exports){ +},{}],148:[function(require,module,exports){ // Copyright 2011 Mark Cavage All rights reserved. // If you have no idea what ASN.1 or BER is, see this: @@ -127267,7 +125569,7 @@ module.exports = { BerReader: Ber.Reader, }; -},{"./ber/index":148}],152:[function(require,module,exports){ +},{"./ber/index":145}],149:[function(require,module,exports){ var _ = require('../utils')._; var utils = require('../utils'); @@ -127340,7 +125642,7 @@ module.exports = { } }; -},{"../utils":160}],153:[function(require,module,exports){ +},{"../utils":157}],150:[function(require,module,exports){ var _ = require('../utils')._; module.exports = { @@ -127373,7 +125675,7 @@ module.exports = { }, }; -},{"../utils":160,"./components":152,"./pkcs1":154,"./pkcs8":155}],154:[function(require,module,exports){ +},{"../utils":157,"./components":149,"./pkcs1":151,"./pkcs8":152}],151:[function(require,module,exports){ (function (Buffer){ var ber = require('../asn1/index').Ber; var _ = require('../utils')._; @@ -127525,7 +125827,7 @@ module.exports = { }; }).call(this,require("buffer").Buffer) -},{"../asn1/index":151,"../utils":160,"buffer":188}],155:[function(require,module,exports){ +},{"../asn1/index":148,"../utils":157,"buffer":184}],152:[function(require,module,exports){ (function (Buffer){ var ber = require('../asn1/index').Ber; var _ = require('../utils')._; @@ -127716,7 +126018,7 @@ module.exports = { }; }).call(this,require("buffer").Buffer) -},{"../asn1/index":151,"../utils":160,"buffer":188}],156:[function(require,module,exports){ +},{"../asn1/index":148,"../utils":157,"buffer":184}],153:[function(require,module,exports){ (function (Buffer){ /* * Basic JavaScript BN library - subset useful for RSA encryption. @@ -128972,7 +127274,7 @@ BigInteger.prototype.square = bnSquare; module.exports = BigInteger; }).call(this,require("buffer").Buffer) -},{"../utils":160,"buffer":188}],157:[function(require,module,exports){ +},{"../utils":157,"buffer":184}],154:[function(require,module,exports){ /* * RSA Encryption / Decryption with PKCS1 v2 Padding. * @@ -129121,7 +127423,7 @@ module.exports.Key = (function () { })(); -},{"../schemes/schemes.js":159,"../utils":160,"../utils.js":160,"./jsbn.js":156}],158:[function(require,module,exports){ +},{"../schemes/schemes.js":156,"../utils":157,"../utils.js":157,"./jsbn.js":153}],155:[function(require,module,exports){ (function (Buffer){ /** * PKCS1 padding and signature scheme @@ -129301,7 +127603,7 @@ function wordArrayToBuffer(wordArray) { } }).call(this,require("buffer").Buffer) -},{"../../crypto-js/crypto-js":127,"../libs/jsbn":156,"buffer":188,"constants":190}],159:[function(require,module,exports){ +},{"../../crypto-js/crypto-js":124,"../libs/jsbn":153,"buffer":184,"constants":186}],156:[function(require,module,exports){ module.exports = { pkcs1: require('./pkcs1'), @@ -129324,7 +127626,7 @@ module.exports = { } }; -},{"./pkcs1":158}],160:[function(require,module,exports){ +},{"./pkcs1":155}],157:[function(require,module,exports){ /* * Utils functions * @@ -129424,7 +127726,7 @@ module.exports.trimSurroundingText = function (data, opening, closing) { return data.substring(trimStartIndex, trimEndIndex); } -},{}],161:[function(require,module,exports){ +},{}],158:[function(require,module,exports){ 'use strict'; var replace = String.prototype.replace; @@ -129444,7 +127746,7 @@ module.exports = { RFC3986: 'RFC3986' }; -},{}],162:[function(require,module,exports){ +},{}],159:[function(require,module,exports){ 'use strict'; var stringify = require('./stringify'); @@ -129457,7 +127759,7 @@ module.exports = { stringify: stringify }; -},{"./formats":161,"./parse":163,"./stringify":164}],163:[function(require,module,exports){ +},{"./formats":158,"./parse":160,"./stringify":161}],160:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -129701,7 +128003,7 @@ module.exports = function (str, opts) { return utils.compact(obj); }; -},{"./utils":165}],164:[function(require,module,exports){ +},{"./utils":162}],161:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -129972,7 +128274,7 @@ module.exports = function (object, opts) { return joined.length > 0 ? prefix + joined : ''; }; -},{"./formats":161,"./utils":165}],165:[function(require,module,exports){ +},{"./formats":158,"./utils":162}],162:[function(require,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty; @@ -130204,13 +128506,14 @@ module.exports = { merge: merge }; -},{}],166:[function(require,module,exports){ +},{}],163:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -130393,6 +128696,7 @@ module.exports = class stex extends Exchange { 'BITSW': 'BITS', 'BHD': 'Bithold', 'BTH': 'Bithereum', + 'MPH': 'Chasyr Token', 'SBTC': 'SBTCT', // SiamBitcoin }, 'options': { @@ -130456,7 +128760,7 @@ module.exports = class stex extends Exchange { // differentiated fees for each particular method const code = this.safeCurrencyCode (this.safeString (currency, 'code')); const precision = this.safeInteger (currency, 'precision'); - const fee = this.safeFloat (currency, 'withdrawal_fee_const'); // todo: redesign + const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign const active = this.safeValue (currency, 'active', true); result[code] = { 'id': id, @@ -130473,11 +128777,11 @@ module.exports = class stex extends Exchange { 'price': { 'min': Math.pow (10, -precision), 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (currency, 'minimum_deposit_amount'), + 'min': this.safeNumber (currency, 'minimum_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal_amount'), + 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'), 'max': undefined, }, }, @@ -130538,11 +128842,11 @@ module.exports = class stex extends Exchange { 'price': this.safeInteger (market, 'market_precision'), }; const active = this.safeValue (market, 'active'); - const minBuyPrice = this.safeFloat (market, 'min_buy_price'); - const minSellPrice = this.safeFloat (market, 'min_sell_price'); + const minBuyPrice = this.safeNumber (market, 'min_buy_price'); + const minSellPrice = this.safeNumber (market, 'min_sell_price'); const minPrice = Math.max (minBuyPrice, minSellPrice); - const buyFee = this.safeFloat (market, 'buy_fee_percent') / 100; - const sellFee = this.safeFloat (market, 'sell_fee_percent') / 100; + const buyFee = this.safeNumber (market, 'buy_fee_percent') / 100; + const sellFee = this.safeNumber (market, 'sell_fee_percent') / 100; const fee = Math.max (buyFee, sellFee); result.push ({ 'id': id, @@ -130561,7 +128865,7 @@ module.exports = class stex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_order_amount'), + 'min': this.safeNumber (market, 'min_order_amount'), 'max': undefined, }, 'price': { 'min': minPrice, 'max': undefined }, @@ -130725,8 +129029,8 @@ module.exports = class stex extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString2 (ticker, 'id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -130739,11 +129043,11 @@ module.exports = class stex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -130753,20 +129057,12 @@ module.exports = class stex extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volumeQuote'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volumeQuote'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker (params); @@ -130832,11 +129128,11 @@ module.exports = class stex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -130911,12 +129207,11 @@ module.exports = class stex extends Exchange { // const id = this.safeString (trade, 'id'); const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; @@ -131029,11 +129324,11 @@ module.exports = class stex extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen_balance'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -131092,9 +129387,9 @@ module.exports = class stex extends Exchange { const marketId = this.safeString2 (order, 'currency_pair_id', 'currency_pair_name'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (order, 'timestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'initial_amount'); - const filled = this.safeFloat (order, 'processed_amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'initial_amount'); + const filled = this.safeNumber (order, 'processed_amount'); let remaining = undefined; let cost = undefined; if (filled !== undefined) { @@ -131124,7 +129419,7 @@ module.exports = class stex extends Exchange { 'order': id, }); } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); const result = { 'info': order, 'id': id, @@ -131155,7 +129450,7 @@ module.exports = class stex extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'amount'); + const feeCost = this.safeNumber (fees[i], 'amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -131739,13 +130034,13 @@ module.exports = class stex extends Exchange { code = currency['code']; } const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status')); const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts'); const updated = this.safeTimestamp (transaction, 'updated_ts'); const txid = this.safeString (transaction, 'txid'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'fee_currency_id', 'deposit_fee_currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -131981,8 +130276,8 @@ module.exports = class stex extends Exchange { for (let i = 0; i < data.length; i++) { const id = this.safeString (data[i], 'id'); const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (data[i], 'withdrawal_fee_const'); - depositFees[code] = this.safeFloat (data[i], 'deposit_fee_const'); + withdrawFees[code] = this.safeNumber (data[i], 'withdrawal_fee_const'); + depositFees[code] = this.safeNumber (data[i], 'deposit_fee_const'); } return { 'withdraw': withdrawFees, @@ -132011,7 +130306,7 @@ module.exports = class stex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],167:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],164:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -132045,13 +130340,14 @@ module.exports = class surbitcoin extends foxbit { } }; -},{"./foxbit.js":87}],168:[function(require,module,exports){ +},{"./foxbit.js":85}],165:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -132219,8 +130515,8 @@ module.exports = class therock extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const buy_fee = this.safeFloat (market, 'buy_fee'); - const sell_fee = this.safeFloat (market, 'sell_fee'); + const buy_fee = this.safeNumber (market, 'buy_fee'); + const sell_fee = this.safeNumber (market, 'sell_fee'); let taker = Math.max (buy_fee, sell_fee); taker = taker / 100; const maker = taker; @@ -132241,11 +130537,11 @@ module.exports = class therock extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_quantity_offer'), + 'min': this.safeNumber (market, 'minimum_quantity_offer'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'minimum_price_offer'), + 'min': this.safeNumber (market, 'minimum_price_offer'), 'max': undefined, }, 'cost': { @@ -132269,11 +130565,11 @@ module.exports = class therock extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'trading_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'trading_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -132292,27 +130588,27 @@ module.exports = class therock extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'close'), // previous day close, if any + 'previousClose': this.safeNumber (ticker, 'close'), // previous day close, if any 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_traded'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume_traded'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -132387,14 +130683,11 @@ module.exports = class therock extends Exchange { const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; let feeCost = undefined; const transactions = this.safeValue (trade, 'transactions', []); @@ -132404,7 +130697,7 @@ module.exports = class therock extends Exchange { if (feeCost === undefined) { feeCost = 0; } - feeCost = this.sum (feeCost, this.safeFloat (feeTransactions[i], 'price')); + feeCost = this.sum (feeCost, this.safeNumber (feeTransactions[i], 'price')); } if (feeCost !== undefined) { fee = { @@ -132559,7 +130852,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (item, 'price'); + const amount = this.safeNumber (item, 'price'); const timestamp = this.parse8601 (this.safeString (item, 'date')); const status = 'ok'; return { @@ -132791,7 +131084,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'price'); + const amount = this.safeNumber (transaction, 'price'); const timestamp = this.parse8601 (this.safeString (transaction, 'date')); const status = 'ok'; // todo parse tags @@ -132966,15 +131259,15 @@ module.exports = class therock extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'date')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'amount_unfilled'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amount_unfilled'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let trades = this.safeValue (order, 'trades'); let cost = undefined; let average = undefined; @@ -133001,7 +131294,7 @@ module.exports = class therock extends Exchange { cost = 0; } } - const stopPrice = this.safeFloat (order, 'conditional_price'); + const stopPrice = this.safeNumber (order, 'conditional_price'); return { 'id': id, 'clientOrderId': undefined, @@ -133279,13 +131572,14 @@ module.exports = class therock extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],169:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],166:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -133464,11 +131758,11 @@ module.exports = class tidebit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -133493,15 +131787,15 @@ module.exports = class tidebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'ask': this.safeFloat (ticker, 'sell'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'ask': this.safeNumber (ticker, 'sell'), 'bidVolume': undefined, 'askVolume': undefined, 'vwap': undefined, @@ -133512,7 +131806,7 @@ module.exports = class tidebit extends Exchange { 'percentage': undefined, 'previousClose': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -133546,9 +131840,14 @@ module.exports = class tidebit extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -133593,11 +131892,11 @@ module.exports = class tidebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -133683,18 +131982,12 @@ module.exports = class tidebit extends Exchange { const id = this.safeString (order, 'id'); const type = this.safeString (order, 'ord_type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const filled = this.safeFloat (order, 'executed_volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - let cost = undefined; - if (price !== undefined) { - if (filled !== undefined) { - cost = price * filled; - } - } - const average = this.safeFloat (order, 'avg_price'); - return { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const filled = this.safeNumber (order, 'executed_volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -133711,12 +132004,12 @@ module.exports = class tidebit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': average, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -133824,11 +132117,12 @@ module.exports = class tidebit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],170:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],167:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class tidex extends Exchange { describe () { @@ -133910,6 +132204,7 @@ module.exports = class tidex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.1 / 100, @@ -133954,19 +132249,48 @@ module.exports = class tidex extends Exchange { async fetchCurrencies (params = {}) { const response = await this.webGetCurrency (params); + // + // [ + // { + // "id":2, + // "symbol":"BTC", + // "type":2, + // "name":"Bitcoin", + // "amountPoint":8, + // "depositEnable":true, + // "depositMinAmount":0.0005, + // "withdrawEnable":true, + // "withdrawFee":0.0004, + // "withdrawMinAmount":0.0005, + // "settings":{ + // "Blockchain":"https://blockchair.com/bitcoin/", + // "TxUrl":"https://blockchair.com/bitcoin/transaction/{0}", + // "AddrUrl":"https://blockchair.com/bitcoin/address/{0}", + // "ConfirmationCount":3, + // "NeedMemo":false + // }, + // "visible":true, + // "isDelisted":false + // } + // ] + // const result = {}; for (let i = 0; i < response.length; i++) { const currency = response[i]; const id = this.safeString (currency, 'symbol'); - const precision = currency['amountPoint']; + const precision = this.safeInteger (currency, 'amountPoint'); const code = this.safeCurrencyCode (id); - let active = currency['visible'] === true; - const canWithdraw = currency['withdrawEnable'] === true; - const canDeposit = currency['depositEnable'] === true; + const visible = this.safeValue (currency, 'visible'); + let active = visible === true; + const withdrawEnable = this.safeValue (currency, 'withdrawEnable'); + const depositEnable = this.safeValue (currency, 'depositEnable'); + const canWithdraw = withdrawEnable === true; + const canDeposit = depositEnable === true; if (!canWithdraw || !canDeposit) { active = false; } const name = this.safeString (currency, 'name'); + const fee = this.safeNumber (currency, 'withdrawFee'); result[code] = { 'id': id, 'code': code, @@ -133976,7 +132300,7 @@ module.exports = class tidex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': currency['withdrawFee'], + 'fee': fee, }, 'deposit': { 'active': canDeposit, @@ -133997,11 +132321,11 @@ module.exports = class tidex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawMinAmount'), + 'min': this.safeNumber (currency, 'withdrawMinAmount'), 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'depositMinAmount'), + 'min': this.safeNumber (currency, 'depositMinAmount'), 'max': undefined, }, }, @@ -134011,26 +132335,25 @@ module.exports = class tidex extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615861869, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":3.0, + // "min_amount":0.001, + // "max_amount":1000000.0, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.1, + // }, + // }, + // } + // const markets = response['pairs']; const keys = Object.keys (markets); const result = []; @@ -134047,19 +132370,20 @@ module.exports = class tidex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }, }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -134068,7 +132392,7 @@ module.exports = class tidex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -134089,11 +132413,11 @@ module.exports = class tidex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (funds, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'value'); - account['used'] = this.safeFloat (balance, 'inOrders'); + account['free'] = this.safeString (balance, 'value'); + account['used'] = this.safeString (balance, 'inOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -134165,16 +132489,16 @@ module.exports = class tidex extends Exchange { timestamp = undefined; } } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -134183,9 +132507,9 @@ module.exports = class tidex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -134233,16 +132557,19 @@ module.exports = class tidex extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const orderId = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = 'limit'; // all trades are still limit trades let takerOrMaker = undefined; let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -134261,12 +132588,6 @@ module.exports = class tidex extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': orderId, @@ -134322,17 +132643,18 @@ module.exports = class tidex extends Exchange { let status = 'open'; let filled = 0.0; let remaining = amount; - if ('return' in response) { - id = this.safeString (response['return'], 'order_id'); + const returnResult = this.safeValue (response, 'return'); + if (returnResult !== undefined) { + id = this.safeString (returnResult, 'order_id'); if (id === '0') { - id = this.safeString (response['return'], 'init_order_id'); + id = this.safeString (returnResult, 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (returnResult, 'received', filled); + remaining = this.safeNumber (returnResult, 'remains', amount); } const timestamp = this.milliseconds (); - return { + return this.safeOrder ({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -134342,7 +132664,7 @@ module.exports = class tidex extends Exchange { 'type': type, 'side': side, 'price': price, - 'cost': price * filled, + 'cost': undefined, 'amount': amount, 'remaining': remaining, 'filled': filled, @@ -134352,7 +132674,7 @@ module.exports = class tidex extends Exchange { 'clientOrderId': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -134381,23 +132703,15 @@ module.exports = class tidex extends Exchange { const symbol = this.safeSymbol (marketId, market); let remaining = undefined; let amount = undefined; - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; + const price = this.safeNumber (order, 'rate'); if ('start_amount' in order) { - amount = this.safeFloat (order, 'start_amount'); - remaining = this.safeFloat (order, 'amount'); + amount = this.safeNumber (order, 'start_amount'); + remaining = this.safeNumber (order, 'amount'); } else { - remaining = this.safeFloat (order, 'amount'); - } - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } + remaining = this.safeNumber (order, 'amount'); } const fee = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -134411,15 +132725,15 @@ module.exports = class tidex extends Exchange { 'side': this.safeString (order, 'type'), 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -134609,11 +132923,12 @@ module.exports = class tidex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],171:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],168:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, PermissionDenied, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, RateLimitExceeded, NotSupported, BadRequest, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class timex extends Exchange { describe () { @@ -135062,11 +133377,11 @@ module.exports = class timex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'totalBalance'); - account['used'] = this.safeFloat (balance, 'lockedBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + account['used'] = this.safeString (balance, 'lockedBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -135427,7 +133742,7 @@ module.exports = class timex extends Exchange { const result = this.safeValue (response, 0, {}); return { 'info': response, - 'maker': this.safeFloat (result, 'fee'), + 'maker': this.safeNumber (result, 'fee'), 'taker': undefined, }; } @@ -135464,18 +133779,18 @@ module.exports = class timex extends Exchange { 'amount': this.precisionFromString (this.safeString (market, 'quantityIncrement')), 'price': this.precisionFromString (this.safeString (market, 'tickSize')), }; - const amountIncrement = this.safeFloat (market, 'quantityIncrement'); - const minBase = this.safeFloat (market, 'baseMinSize'); + const amountIncrement = this.safeNumber (market, 'quantityIncrement'); + const minBase = this.safeNumber (market, 'baseMinSize'); const minAmount = Math.max (amountIncrement, minBase); - const priceIncrement = this.safeFloat (market, 'tickSize'); - const minCost = this.safeFloat (market, 'quoteMinSize'); + const priceIncrement = this.safeNumber (market, 'tickSize'); + const minCost = this.safeNumber (market, 'quoteMinSize'); const limits = { 'amount': { 'min': minAmount, 'max': undefined }, 'price': { 'min': priceIncrement, 'max': undefined }, 'cost': { 'min': Math.max (minCost, minAmount * priceIncrement), 'max': undefined }, }; - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); return { 'id': id, 'symbol': symbol, @@ -135536,7 +133851,7 @@ module.exports = class timex extends Exchange { const name = this.safeString (currency, 'name'); const precision = this.safeInteger (currency, 'decimals'); const active = this.safeValue (currency, 'active'); - // const fee = this.safeFloat (currency, 'withdrawalFee'); + // const fee = this.safeNumber (currency, 'withdrawalFee'); const feeString = this.safeString (currency, 'withdrawalFee'); const tradeDecimals = this.safeInteger (currency, 'tradeDecimals'); let fee = undefined; @@ -135573,14 +133888,6 @@ module.exports = class timex extends Exchange { }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // // { @@ -135600,8 +133907,8 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '/'); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -135617,11 +133924,11 @@ module.exports = class timex extends Exchange { 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -135631,8 +133938,8 @@ module.exports = class timex extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'volumeQuote'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volumeQuote'), }; } @@ -135651,23 +133958,27 @@ module.exports = class timex extends Exchange { // fetchMyTrades, fetchOrder (private) // // { - // "fee": "0.3", - // "id": 100, - // "makerOrTaker": "MAKER", - // "makerOrderId": "string", - // "price": "0.017", - // "quantity": "0.3", + // "id": "7613414", + // "makerOrderId": "0x8420af060722f560098f786a2894d4358079b6ea5d14b395969ed77bc87a623a", + // "takerOrderId": "0x1235ef158a361815b54c9988b6241c85aedcbc1fe81caf8df8587d5ab0373d1a", + // "symbol": "LTCUSDT", // "side": "BUY", - // "symbol": "TIMEETH", - // "takerOrderId": "string", - // "timestamp": "2019-12-08T04:54:11.171Z" - // } + // "quantity": "0.2", + // "fee": "0.22685", + // "feeToken": "USDT", + // "price": "226.85", + // "makerOrTaker": "TAKER", + // "timestamp": "2021-04-09T15:39:45.608" + // } // const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeStringLower2 (trade, 'direction', 'side'); const takerOrMaker = this.safeStringLower (trade, 'makerOrTaker'); @@ -135676,18 +133987,14 @@ module.exports = class timex extends Exchange { orderId = this.safeString (trade, takerOrMaker + 'OrderId'); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); + const feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'feeToken')); if (feeCost !== undefined) { - const feeCurrency = (market === undefined) ? undefined : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrency, }; } - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = this.costToPrecision (symbol, amount * price); - } return { 'info': trade, 'id': id, @@ -135719,11 +134026,11 @@ module.exports = class timex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -135754,14 +134061,12 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'filledQuantity'); - const canceledQuantity = this.safeFloat (order, 'cancelledQuantity'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'filledQuantity'); + const canceledQuantity = this.safeNumber (order, 'cancelledQuantity'); let status = undefined; if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0.0); if (filled >= amount) { status = 'closed'; } else if ((canceledQuantity !== undefined) && (canceledQuantity > 0)) { @@ -135770,30 +134075,19 @@ module.exports = class timex extends Exchange { status = 'open'; } } - const cost = parseFloat (this.costToPrecision (symbol, price * filled)); - const fee = undefined; - let lastTradeTimestamp = undefined; - let trades = undefined; - const rawTrades = this.safeValue (order, 'trades'); - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'order': id, - }); - } - if (trades !== undefined) { - const numTrades = trades.length; - if (numTrades > 0) { - lastTradeTimestamp = trades[numTrades - 1]['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'order': id, + 'type': type, + }); const clientOrderId = this.safeString (order, 'clientOrderId'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': undefined, @@ -135802,14 +134096,14 @@ module.exports = class timex extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { @@ -135850,13 +134144,14 @@ module.exports = class timex extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],172:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],169:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, PermissionDenied, AddressPending } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -136082,9 +134377,9 @@ module.exports = class upbit extends Exchange { } else if ((locked !== undefined) && locked) { active = false; } - const maxOnetimeWithdrawal = this.safeFloat (withdrawLimits, 'onetime'); - const maxDailyWithdrawal = this.safeFloat (withdrawLimits, 'daily', maxOnetimeWithdrawal); - const remainingDailyWithdrawal = this.safeFloat (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); + const maxOnetimeWithdrawal = this.safeNumber (withdrawLimits, 'onetime'); + const maxDailyWithdrawal = this.safeNumber (withdrawLimits, 'daily', maxOnetimeWithdrawal); + const remainingDailyWithdrawal = this.safeNumber (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); let maxWithdrawLimit = undefined; if (remainingDailyWithdrawal > 0) { maxWithdrawLimit = remainingDailyWithdrawal; @@ -136100,11 +134395,11 @@ module.exports = class upbit extends Exchange { 'code': code, 'name': code, 'active': active, - 'fee': this.safeFloat (currencyInfo, 'withdraw_fee'), + 'fee': this.safeNumber (currencyInfo, 'withdraw_fee'), 'precision': precision, 'limits': { 'withdraw': { - 'min': this.safeFloat (withdrawLimits, 'minimum'), + 'min': this.safeNumber (withdrawLimits, 'minimum'), 'max': maxWithdrawLimit, }, }, @@ -136167,8 +134462,8 @@ module.exports = class upbit extends Exchange { }; const state = this.safeString (marketInfo, 'state'); const active = (state === 'active'); - const bidFee = this.safeFloat (response, 'bid_fee'); - const askFee = this.safeFloat (response, 'ask_fee'); + const bidFee = this.safeNumber (response, 'bid_fee'); + const askFee = this.safeNumber (response, 'ask_fee'); const fee = Math.max (bidFee, askFee); return { 'info': response, @@ -136184,7 +134479,7 @@ module.exports = class upbit extends Exchange { 'taker': fee, 'limits': { 'amount': { - 'min': this.safeFloat (ask, 'min_total'), + 'min': this.safeNumber (ask, 'min_total'), 'max': undefined, }, 'price': { @@ -136192,8 +134487,8 @@ module.exports = class upbit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (bid, 'min_total'), - 'max': this.safeFloat (marketInfo, 'max_total'), + 'min': this.safeNumber (bid, 'min_total'), + 'max': this.safeNumber (marketInfo, 'max_total'), }, }, }; @@ -136232,8 +134527,8 @@ module.exports = class upbit extends Exchange { 'price': 8, }; const active = true; - const makerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); - const takerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); + const makerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); + const takerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); result.push ({ 'id': id, 'symbol': symbol, @@ -136286,11 +134581,11 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { @@ -136393,30 +134688,30 @@ module.exports = class upbit extends Exchange { const timestamp = this.safeInteger (ticker, 'trade_timestamp'); const marketId = this.safeString2 (ticker, 'market', 'code'); const symbol = this.safeSymbol (marketId, market, '-'); - const previous = this.safeFloat (ticker, 'prev_closing_price'); - const last = this.safeFloat (ticker, 'trade_price'); - const change = this.safeFloat (ticker, 'signed_change_price'); - const percentage = this.safeFloat (ticker, 'signed_change_rate'); + const previous = this.safeNumber (ticker, 'prev_closing_price'); + const last = this.safeNumber (ticker, 'trade_price'); + const change = this.safeNumber (ticker, 'signed_change_price'); + const percentage = this.safeNumber (ticker, 'signed_change_rate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price'), - 'low': this.safeFloat (ticker, 'low_price'), + 'high': this.safeNumber (ticker, 'high_price'), + 'low': this.safeNumber (ticker, 'low_price'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'opening_price'), + 'open': this.safeNumber (ticker, 'opening_price'), 'close': last, 'last': last, 'previousClose': previous, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'acc_trade_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'acc_trade_price_24h'), + 'baseVolume': this.safeNumber (ticker, 'acc_trade_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'acc_trade_price_24h'), 'info': ticker, }; } @@ -136523,15 +134818,13 @@ module.exports = class upbit extends Exchange { } else if (askOrBid === 'bid') { side = 'buy'; } - let cost = this.safeFloat (trade, 'funds'); - const price = this.safeFloat2 (trade, 'trade_price', 'price'); - const amount = this.safeFloat2 (trade, 'trade_volume', 'volume'); + let cost = this.safeNumber (trade, 'funds'); + const priceString = this.safeString2 (trade, 'trade_price', 'price'); + const amountString = this.safeString2 (trade, 'trade_volume', 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString2 (trade, 'market', 'code'); market = this.safeMarket (marketId, market); @@ -136626,11 +134919,11 @@ module.exports = class upbit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'candle_date_time_utc')), - this.safeFloat (ohlcv, 'opening_price'), - this.safeFloat (ohlcv, 'high_price'), - this.safeFloat (ohlcv, 'low_price'), - this.safeFloat (ohlcv, 'trade_price'), - this.safeFloat (ohlcv, 'candle_acc_trade_volume'), // base volume + this.safeNumber (ohlcv, 'opening_price'), + this.safeNumber (ohlcv, 'high_price'), + this.safeNumber (ohlcv, 'low_price'), + this.safeNumber (ohlcv, 'trade_price'), + this.safeNumber (ohlcv, 'candle_acc_trade_volume'), // base volume ]; } @@ -136899,7 +135192,7 @@ module.exports = class upbit extends Exchange { // } // const id = this.safeString (transaction, 'uuid'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = undefined; // not present in the data structure received from the exchange const tag = undefined; // not present in the data structure received from the exchange const txid = this.safeString (transaction, 'txid'); @@ -136912,7 +135205,7 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -136997,10 +135290,10 @@ module.exports = class upbit extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const status = this.parseOrderStatus (this.safeString (order, 'state')); let lastTradeTimestamp = undefined; - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - const filled = this.safeFloat (order, 'executed_volume'); + let price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const filled = this.safeNumber (order, 'executed_volume'); let cost = undefined; if (type === 'price') { type = 'market'; @@ -137009,7 +135302,7 @@ module.exports = class upbit extends Exchange { } let average = undefined; let fee = undefined; - let feeCost = this.safeFloat (order, 'paid_fee'); + let feeCost = this.safeNumber (order, 'paid_fee'); const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); let trades = this.safeValue (order, 'trades', []); @@ -137032,7 +135325,7 @@ module.exports = class upbit extends Exchange { cost = this.sum (cost, trade['cost']); if (getFeesFromTrades) { const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); + const tradeFeeCost = this.safeNumber (tradeFee, 'cost'); if (tradeFeeCost !== undefined) { feeCost = this.sum (feeCost, tradeFeeCost); } @@ -137174,16 +135467,6 @@ module.exports = class upbit extends Exchange { return this.parseOrder (response); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetDepositsCoinAddresses (params); @@ -137381,212 +135664,7 @@ module.exports = class upbit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],173:[function(require,module,exports){ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); - -// --------------------------------------------------------------------------- - -module.exports = class vaultoro extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'vaultoro', - 'name': 'Vaultoro', - 'countries': [ 'CH' ], - 'rateLimit': 1000, - 'version': '1', - 'has': { - 'CORS': true, - 'fetchMarkets': true, - 'fetchOrderBook': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'fetchTrades': true, - 'fetchTicker': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg', - 'api': 'https://api.vaultoro.com', - 'www': 'https://www.vaultoro.com', - 'doc': 'https://api.vaultoro.com', - }, - 'commonCurrencies': { - 'GLD': 'Gold', - }, - 'api': { - 'public': { - 'get': [ - 'bidandask', - 'buyorders', - 'latest', - 'latesttrades', - 'markets', - 'orderbook', - 'sellorders', - 'transactions/day', - 'transactions/hour', - 'transactions/month', - ], - }, - 'private': { - 'get': [ - 'balance', - 'mytrades', - 'orders', - ], - 'post': [ - 'buy/{symbol}/{type}', - 'cancel/{id}', - 'sell/{symbol}/{type}', - 'withdraw', - ], - }, - }, - }); - } - - async fetchMarkets (params = {}) { - const result = []; - const response = await this.publicGetMarkets (params); - const market = this.safeValue (response, 'data'); - const baseId = this.safeString (market, 'MarketCurrency'); - const quoteId = this.safeString (market, 'BaseCurrency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const id = this.safeString (market, 'MarketName'); - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'active': undefined, - 'precision': this.precision, - 'limits': this.limits, - }); - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetBalance (params); - const balances = this.safeValue (response, 'data'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency_code'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'cash'); - account['used'] = this.safeFloat (balance, 'reserved'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetOrderbook (params); - const orderbook = { - 'bids': response['data'][0]['b'], - 'asks': response['data'][1]['s'], - }; - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'Gold_Price', 'Gold_Amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'Time')); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const price = this.safeFloat (trade, 'Gold_Price'); - const amount = this.safeFloat (trade, 'Gold_Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } - return { - 'id': undefined, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': undefined, - 'side': undefined, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const response = await this.publicGetTransactionsDay (params); - return this.parseTrades (response, market, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const method = 'privatePost' + this.capitalize (side) + 'SymbolType'; - const request = { - 'symbol': market['quoteId'].toLowerCase (), - 'type': type, - 'gld': amount, - 'price': price || 1, - }; - const response = await this[method] (this.extend (request, params)); - return { - 'info': response, - 'id': response['data']['Order_ID'], - }; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - return await this.privatePostCancelId (this.extend (request, params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/'; - if (api === 'public') { - url += path; - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce (); - url += this.version + '/' + this.implodeParams (path, params); - const query = this.extend ({ - 'nonce': nonce, - 'apikey': this.apiKey, - }, this.omit (params, this.extractParams (path))); - url += '?' + this.urlencode (query); - headers = { - 'Content-Type': 'application/json', - 'X-Signature': this.hmac (this.encode (url), this.encode (this.secret)), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } -}; - -},{"./base/Exchange":6}],174:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],170:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -137620,7 +135698,7 @@ module.exports = class vbtc extends foxbit { } }; -},{"./foxbit.js":87}],175:[function(require,module,exports){ +},{"./foxbit.js":85}],171:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -137628,6 +135706,7 @@ module.exports = class vbtc extends foxbit { const Exchange = require ('./base/Exchange'); const { ExchangeError, OrderNotFound, InvalidOrder, BadRequest, AuthenticationError, RateLimitExceeded, RequestTimeout, BadSymbol, AddressPending, PermissionDenied, InsufficientFunds } = require ('./base/errors'); const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -137819,15 +135898,15 @@ module.exports = class vcc extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, 'min'), + 'min': this.safeNumber (amountLimits, 'min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (priceLimits, 'min'), + 'min': this.safeNumber (priceLimits, 'min'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (costLimits, 'min'), + 'min': this.safeNumber (costLimits, 'min'), 'max': undefined, }, }, @@ -137874,12 +135953,12 @@ module.exports = class vcc extends Exchange { 'code': code, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': this.safeInteger (currency, 'decimal'), 'limits': { 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw'), - 'max': this.safeFloat (currency, 'max_withdraw'), + 'min': this.safeNumber (currency, 'min_withdraw'), + 'max': this.safeNumber (currency, 'max_withdraw'), }, }, }; @@ -137902,8 +135981,8 @@ module.exports = class vcc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } @@ -137929,11 +136008,11 @@ module.exports = class vcc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (data, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -137951,11 +136030,11 @@ module.exports = class vcc extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -138044,10 +136123,10 @@ module.exports = class vcc extends Exchange { // } // const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); - const open = this.safeFloat (ticker, 'open_price'); - const last = this.safeFloat (ticker, 'last_price'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); + const open = this.safeNumber (ticker, 'open_price'); + const last = this.safeNumber (ticker, 'last_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -138064,11 +136143,11 @@ module.exports = class vcc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -138182,17 +136261,17 @@ module.exports = class vcc extends Exchange { } market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'base_volume', 'quantity'); - let cost = this.safeFloat2 (trade, 'quote_volume', 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'base_volume', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber2 (trade, 'quote_volume', 'amount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const side = this.safeString2 (trade, 'type', 'trade_type'); const id = this.safeString2 (trade, 'trade_id', 'id'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -138377,7 +136456,7 @@ module.exports = class vcc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -138385,7 +136464,7 @@ module.exports = class vcc extends Exchange { const txid = this.safeString (transaction, 'transaction_id'); const tag = this.safeString (transaction, 'destination_tag'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -138630,46 +136709,27 @@ module.exports = class vcc extends Exchange { const marketId = baseId + '_' + quoteId; market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'executed_quantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - let cost = this.safeFloat (order, 'ceiling'); + const cost = this.safeNumber (order, 'ceiling'); const id = this.safeString (order, 'id'); - let average = undefined; - let price = this.safeFloat (order, 'price'); - // in case of market order - if (!price) { - price = this.safeFloat (order, 'executed_price'); - average = price; - } - let remaining = this.safeFloat (order, 'remaining'); - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if (filled !== undefined) { - if ((amount !== undefined) && (remaining === undefined)) { - remaining = Math.max (0, amount - filled); - } - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((average === undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'executed_price'); + const remaining = this.safeNumber (order, 'remaining'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'trade_type'); const fee = { 'currency': market['quote'], - 'cost': this.safeFloat (order, 'fee'), - 'rate': this.safeFloat (order, 'fee_rate'), + 'cost': this.safeNumber (order, 'fee'), + 'rate': this.safeNumber (order, 'fee_rate'), }; let lastTradeTimestamp = undefined; if (updated !== created) { lastTradeTimestamp = updated; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': id, 'timestamp': created, @@ -138691,7 +136751,7 @@ module.exports = class vcc extends Exchange { 'fee': fee, 'trades': undefined, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -138961,7 +137021,7 @@ module.exports = class vcc extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8,"./base/functions/number":14}],176:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9,"./base/functions/number":15}],172:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -139529,13 +137589,13 @@ module.exports = class wavesexchange extends Exchange { symbol = market['symbol']; } const data = this.safeValue (ticker, 'data', {}); - const last = this.safeFloat (data, 'lastPrice'); - const low = this.safeFloat (data, 'low'); - const high = this.safeFloat (data, 'high'); - const vwap = this.safeFloat (data, 'weightedAveragePrice'); - const baseVolume = this.safeFloat (data, 'volume'); - const quoteVolume = this.safeFloat (data, 'quoteVolume'); - const open = this.safeValue (data, 'firstPrice'); + const last = this.safeNumber (data, 'lastPrice'); + const low = this.safeNumber (data, 'low'); + const high = this.safeNumber (data, 'high'); + const vwap = this.safeNumber (data, 'weightedAveragePrice'); + const baseVolume = this.safeNumber (data, 'volume'); + const quoteVolume = this.safeNumber (data, 'quoteVolume'); + const open = this.safeNumber (data, 'firstPrice'); let change = undefined; let average = undefined; let percentage = undefined; @@ -139689,11 +137749,11 @@ module.exports = class wavesexchange extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.parse8601 (this.safeString (data, 'time')), - this.safeFloat (data, 'open'), - this.safeFloat (data, 'high'), - this.safeFloat (data, 'low'), - this.safeFloat (data, 'close'), - this.safeFloat (data, 'volume', 0), + this.safeNumber (data, 'open'), + this.safeNumber (data, 'high'), + this.safeNumber (data, 'low'), + this.safeNumber (data, 'close'), + this.safeNumber (data, 'volume', 0), ]; } @@ -139908,7 +137968,7 @@ module.exports = class wavesexchange extends Exchange { } if (matcherFee === undefined) { const wavesPrecision = this.safeInteger (this.options, 'wavesPrecision', 8); - const rate = this.safeFloat (rates, matcherFeeAssetId); + const rate = this.safeNumber (rates, matcherFeeAssetId); const code = this.safeCurrencyCode (matcherFeeAssetId); const currency = this.currency (code); const newPrecison = Math.pow (10, wavesPrecision - currency['precision']); @@ -140318,7 +138378,7 @@ module.exports = class wavesexchange extends Exchange { const issueTransaction = this.safeValue (entry, 'issueTransaction'); const decimals = this.safeInteger (issueTransaction, 'decimals'); const currencyId = this.safeString (entry, 'assetId'); - const balance = this.safeFloat (entry, 'balance'); + const balance = this.safeNumber (entry, 'balance'); let code = undefined; if (currencyId in this.currencies_by_id) { code = this.safeCurrencyCode (currencyId); @@ -140348,7 +138408,7 @@ module.exports = class wavesexchange extends Exchange { if (!(code in result)) { result[code] = this.account (); } - const amount = this.safeFloat (reservedBalance, currencyId); + const amount = this.safeNumber (reservedBalance, currencyId); result[code]['used'] = this.currencyFromPrecision (code, amount); } const wavesRequest = { @@ -140361,7 +138421,7 @@ module.exports = class wavesexchange extends Exchange { // "balance": 909085978 // } result['WAVES'] = this.safeValue (result, 'WAVES', {}); - result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeFloat (wavesTotal, 'balance')); + result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeNumber (wavesTotal, 'balance')); const codes = Object.keys (result); for (let i = 0; i < codes.length; i++) { const code = codes[i]; @@ -140453,8 +138513,8 @@ module.exports = class wavesexchange extends Exchange { const datetime = this.safeString (data, 'timestamp'); const timestamp = this.parse8601 (datetime); const id = this.safeString (data, 'id'); - const price = this.safeFloat (data, 'price'); - const amount = this.safeFloat (data, 'amount'); + const price = this.safeNumber (data, 'price'); + const amount = this.safeNumber (data, 'amount'); const order1 = this.safeValue (data, 'order1'); const order2 = this.safeValue (data, 'order2'); let order = undefined; @@ -140478,7 +138538,7 @@ module.exports = class wavesexchange extends Exchange { cost = price * amount; } const fee = { - 'cost': this.safeFloat (data, 'fee'), + 'cost': this.safeNumber (data, 'fee'), 'currency': this.safeCurrencyCode (this.safeString (order, 'matcherFeeAssetId', 'WAVES')), }; return { @@ -140560,7 +138620,7 @@ module.exports = class wavesexchange extends Exchange { const withdrawAddress = await this.privateGetWithdrawAddressesCurrencyAddress (withdrawAddressRequest); const currency = this.safeValue (withdrawAddress, 'currency'); const allowedAmount = this.safeValue (currency, 'allowed_amount'); - const minimum = this.safeFloat (allowedAmount, 'min'); + const minimum = this.safeNumber (allowedAmount, 'min'); if (amount <= minimum) { throw new BadRequest (this.id + ' ' + code + ' withdraw failed, amount ' + amount.toString () + ' must be greater than the minimum allowed amount of ' + minimum.toString ()); } @@ -140630,13 +138690,14 @@ module.exports = class wavesexchange extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],177:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],173:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeNotAvailable, ExchangeError, DDoSProtection, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -140797,7 +138858,7 @@ module.exports = class whitebit extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -140805,7 +138866,7 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minTotal'), + 'min': this.safeNumber (market, 'minTotal'), 'max': undefined, }, }, @@ -140870,8 +138931,8 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -140883,8 +138944,8 @@ module.exports = class whitebit extends Exchange { const response = await this.publicV2GetFee (params); const fees = this.safeValue (response, 'result'); return { - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), }; } @@ -140954,8 +139015,8 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let change = undefined; if (percentage !== undefined) { change = this.numberToString (percentage * 0.01); @@ -140964,22 +139025,22 @@ module.exports = class whitebit extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'deal'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'deal'), 'info': ticker, }; } @@ -141147,8 +139208,11 @@ module.exports = class whitebit extends Exchange { } else { timestamp = parseInt (timestamp * 1000); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'volume'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'volume'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const id = this.safeString2 (trade, 'id', 'tradeId'); let side = this.safeString (trade, 'type'); if (side === undefined) { @@ -141159,10 +139223,6 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined && price !== undefined) { - cost = amount * price; - } return { 'info': trade, 'timestamp': timestamp, @@ -141232,11 +139292,11 @@ module.exports = class whitebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -141285,7 +139345,7 @@ module.exports = class whitebit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],178:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],174:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- @@ -141440,14 +139500,13 @@ module.exports = class xbtce extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'FreeAmount'), - 'used': this.safeFloat (balance, 'LockedAmount'), - 'total': this.safeFloat (balance, 'Amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'FreeAmount'); + account['used'] = this.safeString (balance, 'LockedAmount'); + account['total'] = this.safeString (balance, 'Amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -141559,11 +139618,11 @@ module.exports = class xbtce extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeInteger (ohlcv, 'Timestamp'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -141657,11 +139716,12 @@ module.exports = class xbtce extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],179:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/errors":9}],175:[function(require,module,exports){ 'use strict'; const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, InsufficientFunds, InvalidAddress, BadSymbol, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class xena extends Exchange { describe () { @@ -141937,8 +139997,8 @@ module.exports = class xena extends Exchange { 'price': pricePrecision, 'amount': 0, }; - const maxCost = this.safeFloat (market, 'maxOrderQty'); - const minCost = this.safeFloat (market, 'minOrderQuantity'); + const maxCost = this.safeNumber (market, 'maxOrderQty'); + const minCost = this.safeNumber (market, 'minOrderQuantity'); const limits = { 'amount': { 'min': undefined, @@ -142023,7 +140083,7 @@ module.exports = class xena extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (withdraw, 'commission'), + 'fee': this.safeNumber (withdraw, 'commission'), 'precision': precision, 'limits': { 'amount': { @@ -142039,7 +140099,7 @@ module.exports = class xena extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'minAmount'), + 'min': this.safeNumber (withdraw, 'minAmount'), 'max': undefined, }, }, @@ -142067,8 +140127,8 @@ module.exports = class xena extends Exchange { const timestamp = this.milliseconds (); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPx'); - const open = this.safeFloat (ticker, 'firstPx'); + const last = this.safeNumber (ticker, 'lastPx'); + const open = this.safeNumber (ticker, 'firstPx'); let percentage = undefined; let change = undefined; let average = undefined; @@ -142079,18 +140139,18 @@ module.exports = class xena extends Exchange { percentage = change / open * 100; } } - const buyVolume = this.safeFloat (ticker, 'buyVolume'); - const sellVolume = this.safeFloat (ticker, 'sellVolume'); + const buyVolume = this.safeNumber (ticker, 'buyVolume'); + const sellVolume = this.safeNumber (ticker, 'sellVolume'); const baseVolume = this.sum (buyVolume, sellVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPx'), - 'low': this.safeFloat (ticker, 'lowPx'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'highPx'), + 'low': this.safeNumber (ticker, 'lowPx'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -142267,11 +140327,11 @@ module.exports = class xena extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onHold'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onHold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTrade (trade, market = undefined) { @@ -142325,20 +140385,17 @@ module.exports = class xena extends Exchange { const orderId = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat2 (trade, 'lastPx', 'mdEntryPx'); - const amount = this.safeFloat2 (trade, 'lastQty', 'mdEntrySize'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'lastPx', 'mdEntryPx'); + const amountString = this.safeString2 (trade, 'lastQty', 'mdEntrySize'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (trade, 'commRate'); + const feeRate = this.safeNumber (trade, 'commRate'); fee = { 'cost': feeCost, 'rate': feeRate, @@ -142453,15 +140510,15 @@ module.exports = class xena extends Exchange { // const transactTime = this.safeInteger (ohlcv, 'transactTime'); const timestamp = parseInt (transactTime / 1000000); - const buyVolume = this.safeFloat (ohlcv, 'buyVolume'); - const sellVolume = this.safeFloat (ohlcv, 'sellVolume'); + const buyVolume = this.safeNumber (ohlcv, 'buyVolume'); + const sellVolume = this.safeNumber (ohlcv, 'sellVolume'); const volume = this.sum (buyVolume, sellVolume); return [ timestamp, - this.safeFloat (ohlcv, 'firstPx'), - this.safeFloat (ohlcv, 'highPx'), - this.safeFloat (ohlcv, 'lowPx'), - this.safeFloat (ohlcv, 'lastPx'), + this.safeNumber (ohlcv, 'firstPx'), + this.safeNumber (ohlcv, 'highPx'), + this.safeNumber (ohlcv, 'lowPx'), + this.safeNumber (ohlcv, 'lastPx'), volume, ]; } @@ -142586,11 +140643,10 @@ module.exports = class xena extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); - let cost = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); let side = this.safeStringLower (order, 'side'); if (side === '1') { side = 'buy'; @@ -142607,12 +140663,7 @@ module.exports = class xena extends Exchange { } else if (type === '4') { type = 'stop-limit'; } - if (cost === undefined) { - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -142627,14 +140678,14 @@ module.exports = class xena extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -142687,7 +140738,7 @@ module.exports = class xena extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if ((type === 'stop') || (type === 'stop-limit')) { - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPx param for order type ' + type); } @@ -142766,12 +140817,12 @@ module.exports = class xena extends Exchange { if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); } - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx !== undefined) { request['stopPx'] = this.priceToPrecision (symbol, stopPx); params = this.omit (params, 'stopPx'); } - const capPrice = this.safeFloat (params, 'capPrice'); + const capPrice = this.safeNumber (params, 'capPrice'); if (capPrice !== undefined) { request['capPrice'] = this.priceToPrecision (symbol, capPrice); params = this.omit (params, 'capPrice'); @@ -143126,7 +141177,7 @@ module.exports = class xena extends Exchange { const address = this.safeString (transaction, 'address'); const addressFrom = undefined; const addressTo = address; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const fee = undefined; return { @@ -143223,7 +141274,7 @@ module.exports = class xena extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'kind')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); @@ -143235,11 +141286,11 @@ module.exports = class xena extends Exchange { timestamp = parseInt (timestamp / 1000000); } const fee = { - 'cost': this.safeFloat (item, 'commission'), + 'cost': this.safeNumber (item, 'commission'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -143379,13 +141430,14 @@ module.exports = class xena extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],180:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],176:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError, RateLimitExceeded } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -143520,6 +141572,7 @@ module.exports = class yobit extends Exchange { 'NAV': 'NavajoCoin', 'NBT': 'NiceBytes', 'OMG': 'OMGame', + 'ONX': 'Onix', 'PAC': '$PAC', 'PLAY': 'PlayCoin', 'PIVX': 'Darknet', @@ -143618,15 +141671,33 @@ module.exports = class yobit extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['total'] = this.safeFloat (total, currencyId); + account['free'] = this.safeString (free, currencyId); + account['total'] = this.safeString (total, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615856752, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":10000, + // "min_amount":0.0001, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.2, + // "fee_buyer":0.2, + // "fee_seller":0.2 + // }, + // }, + // } + // const markets = this.safeValue (response, 'pairs'); const keys = Object.keys (markets); const result = []; @@ -143644,15 +141715,15 @@ module.exports = class yobit extends Exchange { 'price': this.safeInteger (market, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }; const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }; const costLimits = { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }; const limits = { 'amount': amountLimits, @@ -143661,6 +141732,7 @@ module.exports = class yobit extends Exchange { }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -143669,7 +141741,7 @@ module.exports = class yobit extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -143745,16 +141817,16 @@ module.exports = class yobit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -143763,9 +141835,9 @@ module.exports = class yobit extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -143814,15 +141886,18 @@ module.exports = class yobit extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const order = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const type = 'limit'; // all trades are still limit trades let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -143837,12 +141912,6 @@ module.exports = class yobit extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, 'taker'); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': order, @@ -143904,8 +141973,8 @@ module.exports = class yobit extends Exchange { id = this.safeString (response['return'], 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (response['return'], 'received', 0.0); + remaining = this.safeNumber (response['return'], 'remains', amount); } const timestamp = this.milliseconds (); return { @@ -143955,21 +142024,13 @@ module.exports = class yobit extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp_created'); const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const remaining = this.safeFloat (order, 'amount'); - const amount = this.safeFloat (order, 'start_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - cost = price * filled; - } - } + const remaining = this.safeNumber (order, 'amount'); + const amount = this.safeNumber (order, 'start_amount'); + const price = this.safeNumber (order, 'rate'); const fee = undefined; const type = 'limit'; const side = this.safeString (order, 'type'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -143983,16 +142044,15 @@ module.exports = class yobit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -144203,13 +142263,14 @@ module.exports = class yobit extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],181:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],177:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -144333,6 +142394,27 @@ module.exports = class zaif extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetCurrencyPairsAll (params); + // + // [ + // { + // "aux_unit_point": 0, + // "item_japanese": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3", + // "aux_unit_step": 5.0, + // "description": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3\u30fb\u65e5\u672c\u5186\u306e\u53d6\u5f15\u3092\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059", + // "item_unit_min": 0.001, + // "event_number": 0, + // "currency_pair": "btc_jpy", + // "is_token": false, + // "aux_unit_min": 5.0, + // "aux_japanese": "\u65e5\u672c\u5186", + // "id": 1, + // "item_unit_step": 0.0001, + // "name": "BTC/JPY", + // "seq": 0, + // "title": "BTC/JPY" + // } + // ] + // const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -144343,8 +142425,8 @@ module.exports = class zaif extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': -Math.log10 (market['item_unit_step']), - 'price': market['aux_unit_point'], + 'amount': -Math.log10 (this.safeNumber (market, 'item_unit_step')), + 'price': this.safeInteger (market, 'aux_unit_point'), }; const fees = this.safeValue (this.options['fees'], symbol, this.fees['trading']); const taker = fees['taker']; @@ -144362,11 +142444,11 @@ module.exports = class zaif extends Exchange { 'maker': maker, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'item_unit_min'), + 'min': this.safeNumber (market, 'item_unit_min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'aux_unit_min'), + 'min': this.safeNumber (market, 'aux_unit_min'), 'max': undefined, }, 'cost': { @@ -144398,7 +142480,7 @@ module.exports = class zaif extends Exchange { }; if ('deposit' in balances) { if (currencyId in balances['deposit']) { - account['total'] = this.safeFloat (balances['deposit'], currencyId); + account['total'] = this.safeNumber (balances['deposit'], currencyId); account['used'] = account['total'] - account['free']; } } @@ -144423,22 +142505,22 @@ module.exports = class zaif extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.milliseconds (); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -144459,14 +142541,11 @@ module.exports = class zaif extends Exchange { side = (side === 'bid') ? 'buy' : 'sell'; const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString2 (trade, 'id', 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); return { @@ -144544,16 +142623,10 @@ module.exports = class zaif extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp'); const marketId = this.safeString (order, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -144567,7 +142640,7 @@ module.exports = class zaif extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': undefined, 'remaining': undefined, @@ -144575,7 +142648,7 @@ module.exports = class zaif extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -144694,13 +142767,14 @@ module.exports = class zaif extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],182:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],178:[function(require,module,exports){ 'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { BadRequest, ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, OrderNotFound, ExchangeNotAvailable, DDoSProtection, InvalidOrder, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -144786,8 +142860,8 @@ module.exports = class zb extends Exchange { 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg', 'api': { - 'public': 'http://api.zb.cn/data', // no https for public API - 'private': 'https://trade.zb.cn/api', + 'public': 'https://api.zb.today/data', + 'private': 'https://trade.zb.today/api', }, 'www': 'https://www.zb.com', 'doc': 'https://www.zb.com/i/developer', @@ -144902,6 +142976,16 @@ module.exports = class zb extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetMarkets (params); + // + // { + // "zb_qc":{ + // "amountScale":2, + // "minAmount":0.01, + // "minSize":5, + // "priceScale":4, + // }, + // } + // const keys = Object.keys (markets); const result = []; for (let i = 0; i < keys.length; i++) { @@ -144965,11 +143049,11 @@ module.exports = class zb extends Exchange { const account = this.account (); const currencyId = this.safeString (balance, 'key'); const code = this.safeCurrencyCode (currencyId); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'freez'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'freez'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -145018,18 +143102,6 @@ module.exports = class zb extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetGetPayinAddress (params); @@ -145136,16 +143208,16 @@ module.exports = class zb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -145155,12 +143227,23 @@ module.exports = class zb extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; } + parseOHLCV (ohlcv, market = undefined) { + return [ + this.safeInteger (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + ]; + } + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -145185,14 +143268,12 @@ module.exports = class zb extends Exchange { let side = this.safeString (trade, 'trade_type'); side = (side === 'bid') ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const costString = Precise.stringMul (priceString, amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (costString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -145371,23 +143452,13 @@ module.exports = class zb extends Exchange { const timestamp = this.safeInteger (order, 'trade_date'); const marketId = this.safeString (order, 'currency'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'trade_amount'); - const amount = this.safeFloat (order, 'total_amount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'trade_money'); - let average = undefined; + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'trade_amount'); + const amount = this.safeNumber (order, 'total_amount'); + const cost = this.safeNumber (order, 'trade_money'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((cost !== undefined) && (filled !== undefined) && (filled > 0)) { - average = cost / filled; - } const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fees'); + const feeCost = this.safeNumber (order, 'fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -145402,7 +143473,7 @@ module.exports = class zb extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -145416,15 +143487,15 @@ module.exports = class zb extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -145487,7 +143558,7 @@ module.exports = class zb extends Exchange { // const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'hash'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let timestamp = this.parse8601 (this.safeString (transaction, 'submit_time')); timestamp = this.safeInteger (transaction, 'submitTime', timestamp); let address = this.safeString2 (transaction, 'toAddress', 'address'); @@ -145507,7 +143578,7 @@ module.exports = class zb extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -145540,7 +143611,7 @@ module.exports = class zb extends Exchange { if (password === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires exchange.password or a safePwd parameter'); } - const fees = this.safeFloat (params, 'fees'); + const fees = this.safeNumber (params, 'fees'); if (fees === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires a fees parameter'); } @@ -145731,7 +143802,7 @@ module.exports = class zb extends Exchange { } }; -},{"./base/Exchange":6,"./base/errors":8}],183:[function(require,module,exports){ +},{"./base/Exchange":6,"./base/Precise":7,"./base/errors":9}],179:[function(require,module,exports){ (function (global){ 'use strict'; @@ -146225,7 +144296,7 @@ var objectKeys = Object.keys || function (obj) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"util/":241}],184:[function(require,module,exports){ +},{"util/":237}],180:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength @@ -146341,9 +144412,9 @@ function fromByteArray (uint8) { return parts.join('') } -},{}],185:[function(require,module,exports){ +},{}],181:[function(require,module,exports){ -},{}],186:[function(require,module,exports){ +},{}],182:[function(require,module,exports){ (function (process,Buffer){ 'use strict'; /* eslint camelcase: "off" */ @@ -146755,7 +144826,7 @@ Zlib.prototype._reset = function () { exports.Zlib = Zlib; }).call(this,require('_process'),require("buffer").Buffer) -},{"_process":210,"assert":183,"buffer":188,"pako/lib/zlib/constants":200,"pako/lib/zlib/deflate.js":202,"pako/lib/zlib/inflate.js":204,"pako/lib/zlib/zstream":208}],187:[function(require,module,exports){ +},{"_process":206,"assert":179,"buffer":184,"pako/lib/zlib/constants":196,"pako/lib/zlib/deflate.js":198,"pako/lib/zlib/inflate.js":200,"pako/lib/zlib/zstream":204}],183:[function(require,module,exports){ (function (process){ 'use strict'; @@ -147367,7 +145438,7 @@ util.inherits(DeflateRaw, Zlib); util.inherits(InflateRaw, Zlib); util.inherits(Unzip, Zlib); }).call(this,require('_process')) -},{"./binding":186,"_process":210,"assert":183,"buffer":188,"stream":229,"util":241}],188:[function(require,module,exports){ +},{"./binding":182,"_process":206,"assert":179,"buffer":184,"stream":225,"util":237}],184:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -149083,7 +147154,7 @@ function numberIsNaN (obj) { return obj !== obj // eslint-disable-line no-self-compare } -},{"base64-js":184,"ieee754":194}],189:[function(require,module,exports){ +},{"base64-js":180,"ieee754":190}],185:[function(require,module,exports){ module.exports = { "100": "Continue", "101": "Switching Protocols", @@ -149149,7 +147220,7 @@ module.exports = { "511": "Network Authentication Required" } -},{}],190:[function(require,module,exports){ +},{}],186:[function(require,module,exports){ module.exports={ "O_RDONLY": 0, "O_WRONLY": 1, @@ -149360,7 +147431,7 @@ module.exports={ "UV_UDP_REUSEADDR": 4 } -},{}],191:[function(require,module,exports){ +},{}],187:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -149471,7 +147542,7 @@ function objectToString(o) { } }).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":196}],192:[function(require,module,exports){ +},{"../../is-buffer/index.js":192}],188:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -149775,7 +147846,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],193:[function(require,module,exports){ +},{}],189:[function(require,module,exports){ var http = require('http') var url = require('url') @@ -149808,7 +147879,7 @@ function validateParams (params) { return params } -},{"http":230,"url":236}],194:[function(require,module,exports){ +},{"http":226,"url":232}],190:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -149894,7 +147965,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],195:[function(require,module,exports){ +},{}],191:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -149919,7 +147990,7 @@ if (typeof Object.create === 'function') { } } -},{}],196:[function(require,module,exports){ +},{}],192:[function(require,module,exports){ /*! * Determine if an object is a Buffer * @@ -149942,14 +148013,14 @@ function isSlowBuffer (obj) { return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) } -},{}],197:[function(require,module,exports){ +},{}],193:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],198:[function(require,module,exports){ +},{}],194:[function(require,module,exports){ 'use strict'; @@ -150056,7 +148127,7 @@ exports.setTyped = function (on) { exports.setTyped(TYPED_OK); -},{}],199:[function(require,module,exports){ +},{}],195:[function(require,module,exports){ 'use strict'; // Note: adler32 takes 12% for level 0 and 2% for level 6. @@ -150109,7 +148180,7 @@ function adler32(adler, buf, len, pos) { module.exports = adler32; -},{}],200:[function(require,module,exports){ +},{}],196:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -150179,7 +148250,7 @@ module.exports = { //Z_NULL: null // Use -1 or null inline, depending on var type }; -},{}],201:[function(require,module,exports){ +},{}],197:[function(require,module,exports){ 'use strict'; // Note: we can't get significant speed boost here. @@ -150240,7 +148311,7 @@ function crc32(crc, buf, len, pos) { module.exports = crc32; -},{}],202:[function(require,module,exports){ +},{}],198:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -152116,7 +150187,7 @@ exports.deflatePrime = deflatePrime; exports.deflateTune = deflateTune; */ -},{"../utils/common":198,"./adler32":199,"./crc32":201,"./messages":206,"./trees":207}],203:[function(require,module,exports){ +},{"../utils/common":194,"./adler32":195,"./crc32":197,"./messages":202,"./trees":203}],199:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -152463,7 +150534,7 @@ module.exports = function inflate_fast(strm, start) { return; }; -},{}],204:[function(require,module,exports){ +},{}],200:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154021,7 +152092,7 @@ exports.inflateSyncPoint = inflateSyncPoint; exports.inflateUndermine = inflateUndermine; */ -},{"../utils/common":198,"./adler32":199,"./crc32":201,"./inffast":203,"./inftrees":205}],205:[function(require,module,exports){ +},{"../utils/common":194,"./adler32":195,"./crc32":197,"./inffast":199,"./inftrees":201}],201:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154366,7 +152437,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 0; }; -},{"../utils/common":198}],206:[function(require,module,exports){ +},{"../utils/common":194}],202:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -154400,7 +152471,7 @@ module.exports = { '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ }; -},{}],207:[function(require,module,exports){ +},{}],203:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -155622,7 +153693,7 @@ exports._tr_flush_block = _tr_flush_block; exports._tr_tally = _tr_tally; exports._tr_align = _tr_align; -},{"../utils/common":198}],208:[function(require,module,exports){ +},{"../utils/common":194}],204:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -155671,7 +153742,7 @@ function ZStream() { module.exports = ZStream; -},{}],209:[function(require,module,exports){ +},{}],205:[function(require,module,exports){ (function (process){ 'use strict'; @@ -155718,7 +153789,7 @@ function nextTick(fn, arg1, arg2, arg3) { } }).call(this,require('_process')) -},{"_process":210}],210:[function(require,module,exports){ +},{"_process":206}],206:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -155904,7 +153975,7 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],211:[function(require,module,exports){ +},{}],207:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.1 by @mathias */ ;(function(root) { @@ -156441,7 +154512,7 @@ process.umask = function() { return 0; }; }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],212:[function(require,module,exports){ +},{}],208:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156527,7 +154598,7 @@ var isArray = Array.isArray || function (xs) { return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],213:[function(require,module,exports){ +},{}],209:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156614,16 +154685,16 @@ var objectKeys = Object.keys || function (obj) { return res; }; -},{}],214:[function(require,module,exports){ +},{}],210:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":212,"./encode":213}],215:[function(require,module,exports){ +},{"./decode":208,"./encode":209}],211:[function(require,module,exports){ module.exports = require('./lib/_stream_duplex.js'); -},{"./lib/_stream_duplex.js":216}],216:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":212}],212:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156748,7 +154819,7 @@ function forEach(xs, f) { f(xs[i], i); } } -},{"./_stream_readable":218,"./_stream_writable":220,"core-util-is":191,"inherits":195,"process-nextick-args":209}],217:[function(require,module,exports){ +},{"./_stream_readable":214,"./_stream_writable":216,"core-util-is":187,"inherits":191,"process-nextick-args":205}],213:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -156796,7 +154867,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":219,"core-util-is":191,"inherits":195}],218:[function(require,module,exports){ +},{"./_stream_transform":215,"core-util-is":187,"inherits":191}],214:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -157806,7 +155877,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./_stream_duplex":216,"./internal/streams/BufferList":221,"./internal/streams/destroy":222,"./internal/streams/stream":223,"_process":210,"core-util-is":191,"events":192,"inherits":195,"isarray":197,"process-nextick-args":209,"safe-buffer":228,"string_decoder/":234,"util":185}],219:[function(require,module,exports){ +},{"./_stream_duplex":212,"./internal/streams/BufferList":217,"./internal/streams/destroy":218,"./internal/streams/stream":219,"_process":206,"core-util-is":187,"events":188,"inherits":191,"isarray":193,"process-nextick-args":205,"safe-buffer":224,"string_decoder/":230,"util":181}],215:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -158021,7 +156092,7 @@ function done(stream, er, data) { return stream.push(null); } -},{"./_stream_duplex":216,"core-util-is":191,"inherits":195}],220:[function(require,module,exports){ +},{"./_stream_duplex":212,"core-util-is":187,"inherits":191}],216:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -158688,7 +156759,7 @@ Writable.prototype._destroy = function (err, cb) { cb(err); }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./_stream_duplex":216,"./internal/streams/destroy":222,"./internal/streams/stream":223,"_process":210,"core-util-is":191,"inherits":195,"process-nextick-args":209,"safe-buffer":228,"util-deprecate":238}],221:[function(require,module,exports){ +},{"./_stream_duplex":212,"./internal/streams/destroy":218,"./internal/streams/stream":219,"_process":206,"core-util-is":187,"inherits":191,"process-nextick-args":205,"safe-buffer":224,"util-deprecate":234}],217:[function(require,module,exports){ 'use strict'; /**/ @@ -158763,7 +156834,7 @@ module.exports = function () { return BufferList; }(); -},{"safe-buffer":228}],222:[function(require,module,exports){ +},{"safe-buffer":224}],218:[function(require,module,exports){ 'use strict'; /**/ @@ -158836,13 +156907,13 @@ module.exports = { destroy: destroy, undestroy: undestroy }; -},{"process-nextick-args":209}],223:[function(require,module,exports){ +},{"process-nextick-args":205}],219:[function(require,module,exports){ module.exports = require('events').EventEmitter; -},{"events":192}],224:[function(require,module,exports){ +},{"events":188}],220:[function(require,module,exports){ module.exports = require('./readable').PassThrough -},{"./readable":225}],225:[function(require,module,exports){ +},{"./readable":221}],221:[function(require,module,exports){ exports = module.exports = require('./lib/_stream_readable.js'); exports.Stream = exports; exports.Readable = exports; @@ -158851,13 +156922,13 @@ exports.Duplex = require('./lib/_stream_duplex.js'); exports.Transform = require('./lib/_stream_transform.js'); exports.PassThrough = require('./lib/_stream_passthrough.js'); -},{"./lib/_stream_duplex.js":216,"./lib/_stream_passthrough.js":217,"./lib/_stream_readable.js":218,"./lib/_stream_transform.js":219,"./lib/_stream_writable.js":220}],226:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":212,"./lib/_stream_passthrough.js":213,"./lib/_stream_readable.js":214,"./lib/_stream_transform.js":215,"./lib/_stream_writable.js":216}],222:[function(require,module,exports){ module.exports = require('./readable').Transform -},{"./readable":225}],227:[function(require,module,exports){ +},{"./readable":221}],223:[function(require,module,exports){ module.exports = require('./lib/_stream_writable.js'); -},{"./lib/_stream_writable.js":220}],228:[function(require,module,exports){ +},{"./lib/_stream_writable.js":216}],224:[function(require,module,exports){ /* eslint-disable node/no-deprecated-api */ var buffer = require('buffer') var Buffer = buffer.Buffer @@ -158921,7 +156992,7 @@ SafeBuffer.allocUnsafeSlow = function (size) { return buffer.SlowBuffer(size) } -},{"buffer":188}],229:[function(require,module,exports){ +},{"buffer":184}],225:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -159050,7 +157121,7 @@ Stream.prototype.pipe = function(dest, options) { return dest; }; -},{"events":192,"inherits":195,"readable-stream/duplex.js":215,"readable-stream/passthrough.js":224,"readable-stream/readable.js":225,"readable-stream/transform.js":226,"readable-stream/writable.js":227}],230:[function(require,module,exports){ +},{"events":188,"inherits":191,"readable-stream/duplex.js":211,"readable-stream/passthrough.js":220,"readable-stream/readable.js":221,"readable-stream/transform.js":222,"readable-stream/writable.js":223}],226:[function(require,module,exports){ (function (global){ var ClientRequest = require('./lib/request') var extend = require('xtend') @@ -159132,7 +157203,7 @@ http.METHODS = [ 'UNSUBSCRIBE' ] }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./lib/request":232,"builtin-status-codes":189,"url":236,"xtend":242}],231:[function(require,module,exports){ +},{"./lib/request":228,"builtin-status-codes":185,"url":232,"xtend":238}],227:[function(require,module,exports){ (function (global){ exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream) @@ -159205,7 +157276,7 @@ function isFunction (value) { xhr = null // Help gc }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],232:[function(require,module,exports){ +},{}],228:[function(require,module,exports){ (function (process,global,Buffer){ var capability = require('./capability') var inherits = require('inherits') @@ -159515,7 +157586,7 @@ var unsafeHeaders = [ ] }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"./capability":231,"./response":233,"_process":210,"buffer":188,"inherits":195,"readable-stream":225,"to-arraybuffer":235}],233:[function(require,module,exports){ +},{"./capability":227,"./response":229,"_process":206,"buffer":184,"inherits":191,"readable-stream":221,"to-arraybuffer":231}],229:[function(require,module,exports){ (function (process,global,Buffer){ var capability = require('./capability') var inherits = require('inherits') @@ -159701,7 +157772,7 @@ IncomingMessage.prototype._onXHRProgress = function () { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"./capability":231,"_process":210,"buffer":188,"inherits":195,"readable-stream":225}],234:[function(require,module,exports){ +},{"./capability":227,"_process":206,"buffer":184,"inherits":191,"readable-stream":221}],230:[function(require,module,exports){ 'use strict'; var Buffer = require('safe-buffer').Buffer; @@ -159974,7 +158045,7 @@ function simpleWrite(buf) { function simpleEnd(buf) { return buf && buf.length ? this.write(buf) : ''; } -},{"safe-buffer":228}],235:[function(require,module,exports){ +},{"safe-buffer":224}],231:[function(require,module,exports){ var Buffer = require('buffer').Buffer module.exports = function (buf) { @@ -160003,7 +158074,7 @@ module.exports = function (buf) { } } -},{"buffer":188}],236:[function(require,module,exports){ +},{"buffer":184}],232:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -160737,7 +158808,7 @@ Url.prototype.parseHost = function() { if (host) this.hostname = host; }; -},{"./util":237,"punycode":211,"querystring":214}],237:[function(require,module,exports){ +},{"./util":233,"punycode":207,"querystring":210}],233:[function(require,module,exports){ 'use strict'; module.exports = { @@ -160755,7 +158826,7 @@ module.exports = { } }; -},{}],238:[function(require,module,exports){ +},{}],234:[function(require,module,exports){ (function (global){ /** @@ -160826,16 +158897,16 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],239:[function(require,module,exports){ -arguments[4][195][0].apply(exports,arguments) -},{"dup":195}],240:[function(require,module,exports){ +},{}],235:[function(require,module,exports){ +arguments[4][191][0].apply(exports,arguments) +},{"dup":191}],236:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],241:[function(require,module,exports){ +},{}],237:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -161425,7 +159496,7 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":240,"_process":210,"inherits":239}],242:[function(require,module,exports){ +},{"./support/isBuffer":236,"_process":206,"inherits":235}],238:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aax.js index 9c71e445f..3b8be7dc2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, ExchangeNotAvailable, OrderNotFound, InvalidOrder, CancelPending, RateLimitExceeded, InsufficientFunds, BadRequest, BadSymbol, PermissionDenied } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -35,6 +36,7 @@ module.exports = class aax extends Exchange { 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, + 'fetchStatus': true, 'fetchTicker': 'emulated', 'fetchTickers': true, 'fetchTrades': true, @@ -233,6 +235,37 @@ module.exports = class aax extends Exchange { }); } + async fetchStatus (params = {}) { + const response = await this.publicGetAnnouncementMaintenance (params); + // + // { + // "code": 1, + // "data": { + // "startTime":"2020-06-25T02:15:00.000Z", + // "endTime":"2020-06-25T02:45:00.000Z", + // "description":"Spot Trading :UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45),Futures Trading: UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45).We apologize for any inconvenience caused. Thank you for your patience and understanding.Should you have any enquiries, please do not hesitate our live chat support or via email at cs@aax.com." + // }, + // "message":"success", + // "ts":1593043237000 + // } + // + const data = this.safeValue (response, 'data', {}); + const timestamp = this.milliseconds (); + const startTime = this.parse8601 (this.safeString (data, 'startTime')); + const endTime = this.parse8601 (this.safeString (data, 'endTime')); + const update = { + 'updated': this.safeInteger (response, 'ts', timestamp), + }; + if (endTime !== undefined) { + const startTimeIsOk = (startTime === undefined) ? true : (timestamp < startTime); + const isOk = (timestamp > endTime) || startTimeIsOk; + update['eta'] = endTime; + update['status'] = isOk ? 'ok' : 'maintenance'; + } + this.status = this.extend (this.status, update); + return this.status; + } + async fetchMarkets (params = {}) { const response = await this.publicGetInstruments (params); // @@ -318,8 +351,8 @@ module.exports = class aax extends Exchange { const quote = this.safeCurrencyCode (quoteId); const status = this.safeString (market, 'status'); const active = (status === 'enable'); - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); const type = this.safeString (market, 'type'); let inverse = undefined; let linear = undefined; @@ -337,8 +370,8 @@ module.exports = class aax extends Exchange { symbol = base + '/' + quote; } const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; result.push ({ 'id': id, @@ -396,8 +429,8 @@ module.exports = class aax extends Exchange { const timestamp = this.safeInteger (ticker, 't'); const marketId = this.safeString (ticker, 's'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'c'); - const open = this.safeFloat (ticker, 'o'); + const last = this.safeNumber (ticker, 'c'); + const open = this.safeNumber (ticker, 'o'); let change = undefined; let percentage = undefined; let average = undefined; @@ -408,13 +441,13 @@ module.exports = class aax extends Exchange { } average = this.sum (last, open) / 2; } - const quoteVolume = this.safeFloat (ticker, 'v'); + const quoteVolume = this.safeNumber (ticker, 'v'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'h'), - 'low': this.safeFloat (ticker, 'l'), + 'high': this.safeNumber (ticker, 'h'), + 'low': this.safeNumber (ticker, 'l'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -561,8 +594,8 @@ module.exports = class aax extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let price = this.safeFloat2 (trade, 'p', 'filledPrice'); - const amount = this.safeFloat2 (trade, 'q', 'filledQty'); + let priceString = this.safeString2 (trade, 'p', 'filledPrice'); + const amountString = this.safeString2 (trade, 'q', 'filledQty'); const orderId = this.safeString (trade, 'orderID'); const isTaker = this.safeValue (trade, 'taker'); let takerOrMaker = undefined; @@ -576,17 +609,15 @@ module.exports = class aax extends Exchange { side = 'sell'; } if (side === undefined) { - side = (price > 0) ? 'buy' : 'sell'; - } - side = (price > 0) ? 'buy' : 'sell'; - price = Math.abs (price); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; + side = (priceString[0] === '-') ? 'sell' : 'buy'; } + priceString = (priceString[0] === '-') ? priceString.slice (1) : priceString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderType = this.parseOrderType (this.safeString (trade, 'orderType')); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { @@ -654,11 +685,11 @@ module.exports = class aax extends Exchange { // return [ this.safeTimestamp (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -743,12 +774,12 @@ module.exports = class aax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'unavailable'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'unavailable'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -776,7 +807,7 @@ module.exports = class aax extends Exchange { request['clOrdID'] = clientOrderId; params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { if ((orderType === 'STOP-LIMIT') || (orderType === 'STOP')) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders'); @@ -894,7 +925,7 @@ module.exports = class aax extends Exchange { // 'price': this.priceToPrecision (symbol, price), // 'stopPrice': this.priceToPrecision (symbol, stopPrice), }; - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1531,15 +1562,18 @@ module.exports = class aax extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const price = this.safeFloat (order, 'price'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const price = this.safeNumber (order, 'price'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'Post-Only'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeString (order, 'leavesQty'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + let remaining = this.safeNumber (order, 'leavesQty'); + if ((filled === 0) && (remaining === 0)) { + remaining = undefined; + } let cost = undefined; let lastTradeTimestamp = undefined; if (filled !== undefined) { @@ -1554,7 +1588,7 @@ module.exports = class aax extends Exchange { } } let fee = undefined; - const feeCost = this.safeFloat (order, 'commission'); + const feeCost = this.safeNumber (order, 'commission'); if (feeCost !== undefined) { let feeCurrency = undefined; if (market !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/acx.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/acx.js deleted file mode 100644 index e10ec85ca..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/acx.js +++ /dev/null @@ -1,487 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { InsufficientFunds, OrderNotFound } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class acx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'acx', - 'name': 'ACX', - 'countries': [ 'AU' ], - 'rateLimit': 1000, - 'version': 'v2', - 'has': { - 'cancelOrder': true, - 'CORS': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchMarkets': true, - 'fetchOHLCV': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTime': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'timeframes': { - '1m': '1', - '5m': '5', - '15m': '15', - '30m': '30', - '1h': '60', - '2h': '120', - '4h': '240', - '12h': '720', - '1d': '1440', - '3d': '4320', - '1w': '10080', - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/30247614-1fe61c74-9621-11e7-9e8c-f1a627afa279.jpg', - 'extension': '.json', - 'api': 'https://acx.io/api', - 'www': 'https://acx.io', - 'doc': 'https://acx.io/documents/api_v2', - }, - 'api': { - 'public': { - 'get': [ - 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. - 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator - 'k', // Get OHLC(k line) of specific market - 'markets', // Get all available markets - 'order_book', // Get the order book of specified market - 'order_book/{market}', - 'tickers', // Get ticker of all markets - 'tickers/{market}', // Get ticker of specific market - 'timestamp', // Get server current time, in seconds since Unix epoch - 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. - 'trades/{market}', - ], - }, - 'private': { - 'get': [ - 'members/me', // Get your profile and accounts info - 'deposits', // Get your deposits history - 'deposit', // Get details of specific deposit - 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. - 'orders', // Get your orders, results is paginated - 'order', // Get information of specified order - 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. - 'withdraws', // Get your cryptocurrency withdraws - 'withdraw', // Get your cryptocurrency withdraw - ], - 'post': [ - 'orders', // Create a Sell/Buy order - 'orders/multi', // Create multiple sell/buy orders - 'orders/clear', // Cancel all my orders - 'order/delete', // Cancel an order - 'withdraw', // Create a withdraw - ], - }, - }, - 'fees': { - 'trading': { - 'tierBased': false, - 'percentage': true, - 'maker': 0.2 / 100, - 'taker': 0.2 / 100, - }, - 'funding': { - 'tierBased': false, - 'percentage': true, - 'withdraw': {}, // There is only 1% fee on withdrawals to your bank account. - }, - }, - 'commonCurrencies': { - 'PLA': 'Plair', - }, - 'exceptions': { - '2002': InsufficientFunds, - '2003': OrderNotFound, - }, - }); - } - - async fetchMarkets (params = {}) { - const markets = await this.publicGetMarkets (params); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = market['id']; - const symbol = market['name']; - let baseId = this.safeString (market, 'base_unit'); - let quoteId = this.safeString (market, 'quote_unit'); - if ((baseId === undefined) || (quoteId === undefined)) { - const ids = symbol.split ('/'); - baseId = ids[0].toLowerCase (); - quoteId = ids[1].toLowerCase (); - } - let base = baseId.toUpperCase (); - let quote = quoteId.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - // todo: find out their undocumented precision and limits - const precision = { - 'amount': 8, - 'price': 8, - }; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'precision': precision, - 'info': market, - 'active': undefined, - 'limits': this.limits, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetMembersMe (params); - const balances = this.safeValue (response, 'accounts'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 300 - } - const orderbook = await this.publicGetDepth (this.extend (request, params)); - const timestamp = this.safeTimestamp (orderbook, 'timestamp'); - return this.parseOrderBook (orderbook, timestamp); - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.safeTimestamp (ticker, 'at'); - ticker = ticker['ticker']; - let symbol = undefined; - if (market) { - symbol = market['symbol']; - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': undefined, - 'info': ticker, - }; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetTickers (params); - const ids = Object.keys (response); - const result = {}; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let market = undefined; - let symbol = id; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } else { - let base = id.slice (0, 3); - let quote = id.slice (3, 6); - base = base.toUpperCase (); - quote = quote.toUpperCase (); - base = this.safeCurrencyCode (base); - quote = this.safeCurrencyCode (quote); - symbol = base + '/' + quote; - } - result[symbol] = this.parseTicker (response[id], market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTickersMarket (this.extend (request, params)); - return this.parseTicker (response, market); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const id = this.safeString (trade, 'tid'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'info': trade, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': undefined, - 'side': undefined, - 'order': undefined, - 'takerOrMaker': undefined, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), - 'cost': this.safeFloat (trade, 'funds'), - 'fee': undefined, - }; - } - - async fetchTime (params = {}) { - const response = await this.publicGetTimestamp (params); - // - // 1594911427 - // - return response * 1000; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - return [ - this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (limit === undefined) { - limit = 500; // default is 30 - } - const request = { - 'market': market['id'], - 'period': this.timeframes[timeframe], - 'limit': limit, - }; - if (since !== undefined) { - request['timestamp'] = parseInt (since / 1000); - } - const response = await this.publicGetK (this.extend (request, params)); - return this.parseOHLCVs (response, market, timeframe, since, limit); - } - - parseOrderStatus (status) { - const statuses = { - 'done': 'closed', - 'wait': 'open', - 'cancel': 'canceled', - }; - return this.safeString (statuses, status, status); - } - - parseOrder (order, market = undefined) { - const marketId = this.safeString (order, 'market'); - const symbol = this.safeSymbol (marketId, market); - const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const status = this.parseOrderStatus (this.safeString (order, 'state')); - const type = this.safeString (order, 'type'); - const side = this.safeString (order, 'side'); - const id = this.safeString (order, 'id'); - return { - 'id': id, - 'clientOrderId': undefined, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': this.safeFloat (order, 'price'), - 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'volume'), - 'filled': this.safeFloat (order, 'executed_volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'trades': undefined, - 'fee': undefined, - 'info': order, - 'cost': undefined, - 'average': undefined, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': parseInt (id), - }; - const response = await this.privateGetOrder (this.extend (request, params)); - return this.parseOrder (response); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'market': this.marketId (symbol), - 'side': side, - 'volume': amount.toString (), - 'ord_type': type, - }; - if (type === 'limit') { - request['price'] = price.toString (); - } - const response = await this.privatePostOrders (this.extend (request, params)); - const marketId = this.safeValue (response, 'market'); - const market = this.safeValue (this.markets_by_id, marketId); - return this.parseOrder (response, market); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - const response = await this.privatePostOrderDelete (this.extend (request, params)); - const order = this.parseOrder (response); - const status = order['status']; - if (status === 'closed' || status === 'canceled') { - throw new OrderNotFound (this.id + ' ' + this.json (order)); - } - return order; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - // they have XRP but no docs on memo/tag - const request = { - 'currency': currency['id'], - 'sum': amount, - 'address': address, - }; - const response = await this.privatePostWithdraw (this.extend (request, params)); - // withdrawal response is undocumented - return { - 'info': response, - 'id': undefined, - }; - } - - nonce () { - return this.milliseconds (); - } - - encodeParams (params) { - if ('orders' in params) { - const orders = params['orders']; - let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); - for (let i = 0; i < orders.length; i++) { - const order = orders[i]; - const keys = Object.keys (order); - for (let k = 0; k < keys.length; k++) { - const key = keys[k]; - const value = order[key]; - query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); - } - } - return query; - } - return this.urlencode (this.keysort (params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let request = '/api/' + this.version + '/' + this.implodeParams (path, params); - if ('extension' in this.urls) { - request += this.urls['extension']; - } - const query = this.omit (params, this.extractParams (path)); - let url = this.urls['api'] + request; - if (api === 'public') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce ().toString (); - const query = this.encodeParams (this.extend ({ - 'access_key': this.apiKey, - 'tonce': nonce, - }, params)); - const auth = method + '|' + request + '|' + query; - const signed = this.hmac (this.encode (auth), this.encode (this.secret)); - const suffix = query + '&signature=' + signed; - if (method === 'GET') { - url += '?' + suffix; - } else { - body = suffix; - headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; - } - if (code === 400) { - const error = this.safeValue (response, 'error'); - const errorCode = this.safeString (error, 'code'); - const feedback = this.id + ' ' + this.json (response); - this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); - // fallback to default error handler - } - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aofex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aofex.js index 7899f09d5..69264394e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aofex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/aofex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, BadSymbol, InvalidOrder, PermissionDenied, InvalidAddress, AuthenticationError, InvalidNonce, BadRequest, InsufficientFunds, OrderNotFound } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -193,8 +194,8 @@ module.exports = class aofex extends Exchange { const symbol = base + '/' + quote; const numericId = this.safeInteger (market, 'id'); const precision = this.safeValue (precisions, id, {}); - const makerFee = this.safeFloat (market, 'maker_fee'); - const takerFee = this.safeFloat (market, 'taker_fee'); + const makerFee = this.safeNumber (market, 'maker_fee'); + const takerFee = this.safeNumber (market, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -212,12 +213,12 @@ module.exports = class aofex extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -245,11 +246,11 @@ module.exports = class aofex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -328,11 +329,11 @@ module.exports = class aofex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -355,8 +356,8 @@ module.exports = class aofex extends Exchange { return { 'info': response, 'symbol': symbol, - 'maker': this.safeFloat (result, 'fromFee'), - 'taker': this.safeFloat (result, 'toFee'), + 'maker': this.safeNumber (result, 'fromFee'), + 'taker': this.safeNumber (result, 'toFee'), }; } @@ -413,8 +414,8 @@ module.exports = class aofex extends Exchange { if (market) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); let change = undefined; if (symbol !== undefined) { change = parseFloat (this.priceToPrecision (symbol, last - open)); @@ -423,8 +424,8 @@ module.exports = class aofex extends Exchange { } const average = this.sum (last, open) / 2; const percentage = change / open * 100; - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); let vwap = this.vwap (baseVolume, quoteVolume); if (vwap !== undefined) { vwap = parseFloat (this.priceToPrecision (symbol, vwap)); @@ -433,8 +434,8 @@ module.exports = class aofex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -552,13 +553,15 @@ module.exports = class aofex extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'number'); - let cost = this.safeFloat (trade, 'total_price'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'number'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total_price'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -702,21 +705,21 @@ module.exports = class aofex extends Exchange { const orderType = this.safeString (order, 'type'); const type = (orderType === '2') ? 'limit' : 'market'; const side = this.safeString (order, 'side'); - // const amount = this.safeFloat (order, 'number'); - // const price = this.safeFloat (order, 'price'); + // const amount = this.safeNumber (order, 'number'); + // const price = this.safeNumber (order, 'price'); let cost = undefined; let price = undefined; let amount = undefined; let average = undefined; - const number = this.safeFloat (order, 'number'); - const totalPrice = this.safeFloat (order, 'total_price'); + const number = this.safeNumber (order, 'number'); + const totalPrice = this.safeNumber (order, 'total_price'); if (type === 'limit') { amount = number; - price = this.safeFloat (order, 'price'); + price = this.safeNumber (order, 'price'); } else { - average = this.safeFloat (order, 'deal_price'); + average = this.safeNumber (order, 'deal_price'); if (side === 'buy') { - amount = this.safeFloat (order, 'deal_number'); + amount = this.safeNumber (order, 'deal_number'); } else { amount = number; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ascendex.js similarity index 93% rename from Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmax.js rename to Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ascendex.js index 62cbf55d5..753148db2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Sensor-Bot/Exchange-Raw-Data/node_modules/ccxt/js/bitmax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ascendex.js @@ -4,16 +4,17 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class bitmax extends Exchange { +module.exports = class ascendex extends Exchange { describe () { return this.deepExtend (super.describe (), { - 'id': 'bitmax', - 'name': 'BitMax', - 'countries': [ 'CN' ], // China + 'id': 'ascendex', + 'name': 'AscendEX', + 'countries': [ 'SG', 'CN' ], // Singapore, China 'rateLimit': 500, // new metainfo interface 'has': { @@ -55,14 +56,14 @@ module.exports = class bitmax extends Exchange { }, 'version': 'v1', 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg', - 'api': 'https://bitmax.io', + 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg', + 'api': 'https://ascendex.com', 'test': 'https://bitmax-test.io', - 'www': 'https://bitmax.io', + 'www': 'https://ascendex.com', 'doc': [ 'https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation', ], - 'fees': 'https://bitmax.io/#/feeRate/tradeRate', + 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate', 'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM', }, 'api': { @@ -131,6 +132,7 @@ module.exports = class bitmax extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'taker': 0.002, @@ -212,6 +214,7 @@ module.exports = class bitmax extends Exchange { 'broad': {}, }, 'commonCurrencies': { + 'BOND': 'BONDED', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', }, @@ -294,7 +297,7 @@ module.exports = class bitmax extends Exchange { const code = this.safeCurrencyCode (id); const precision = this.safeInteger2 (currency, 'precisionScale', 'nativeScale'); // why would the exchange API have different names for the same field - const fee = this.safeFloat2 (currency, 'withdrawFee', 'withdrawalFee'); + const fee = this.safeNumber2 (currency, 'withdrawFee', 'withdrawalFee'); const status = this.safeString2 (currency, 'status', 'statusCode'); const active = (status === 'Normal'); const margin = ('borrowAssetCode' in currency); @@ -322,7 +325,7 @@ module.exports = class bitmax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawalAmt'), + 'min': this.safeNumber (currency, 'minWithdrawalAmt'), 'max': undefined, }, }, @@ -423,8 +426,8 @@ module.exports = class bitmax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'Normal'); @@ -450,16 +453,16 @@ module.exports = class bitmax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minQty'), - 'max': this.safeFloat (market, 'maxQty'), + 'min': this.safeNumber (market, 'minQty'), + 'max': this.safeNumber (market, 'maxQty'), }, 'price': { - 'min': this.safeFloat (market, 'tickSize'), + 'min': this.safeNumber (market, 'tickSize'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minNotional'), - 'max': this.safeFloat (market, 'maxNotional'), + 'min': this.safeNumber (market, 'minNotional'), + 'max': this.safeNumber (market, 'maxNotional'), }, }, }); @@ -467,28 +470,6 @@ module.exports = class bitmax extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - // TODO: fee calculation here is incorrect, we need to support tiered fee calculation. - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { let accountGroup = this.safeString (this.options, 'account-group'); let response = undefined; @@ -593,11 +574,11 @@ module.exports = class bitmax extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'asset')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -669,10 +650,10 @@ module.exports = class bitmax extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', []); const ask = this.safeValue (ticker, 'ask', []); - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; let average = undefined; @@ -687,12 +668,12 @@ module.exports = class bitmax extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 0), - 'bidVolume': this.safeFloat (bid, 1), - 'ask': this.safeFloat (ask, 0), - 'askVolume': this.safeFloat (ask, 1), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 0), + 'bidVolume': this.safeNumber (bid, 1), + 'ask': this.safeNumber (ask, 0), + 'askVolume': this.safeNumber (ask, 1), 'vwap': undefined, 'open': open, 'close': close, @@ -701,20 +682,12 @@ module.exports = class bitmax extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -791,11 +764,11 @@ module.exports = class bitmax extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.safeInteger (data, 'ts'), - this.safeFloat (data, 'o'), - this.safeFloat (data, 'h'), - this.safeFloat (data, 'l'), - this.safeFloat (data, 'c'), - this.safeFloat (data, 'v'), + this.safeNumber (data, 'o'), + this.safeNumber (data, 'h'), + this.safeNumber (data, 'l'), + this.safeNumber (data, 'c'), + this.safeNumber (data, 'v'), ]; } @@ -860,12 +833,11 @@ module.exports = class bitmax extends Exchange { // } // const timestamp = this.safeInteger (trade, 'ts'); - const price = this.safeFloat2 (trade, 'price', 'p'); - const amount = this.safeFloat (trade, 'q'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString2 (trade, 'price', 'p'); + const amountString = this.safeString (trade, 'q'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const buyerIsMaker = this.safeValue (trade, 'bm', false); const makerOrTaker = buyerIsMaker ? 'maker' : 'taker'; const side = buyerIsMaker ? 'buy' : 'sell'; @@ -989,26 +961,12 @@ module.exports = class bitmax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '/'); - let timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); - let lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const average = this.safeFloat (order, 'avgPx'); - const filled = this.safeFloat2 (order, 'cumFilledQty', 'cumQty'); - let remaining = undefined; - if (filled !== undefined) { - if (filled === 0) { - timestamp = lastTradeTimestamp; - lastTradeTimestamp = undefined; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - let cost = undefined; - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } + const timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime'); + const lastTradeTimestamp = this.safeInteger (order, 'lastExecTime'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const average = this.safeNumber (order, 'avgPx'); + const filled = this.safeNumber2 (order, 'cumFilledQty', 'cumQty'); const id = this.safeString (order, 'orderId'); let clientOrderId = this.safeString (order, 'id'); if (clientOrderId !== undefined) { @@ -1018,7 +976,7 @@ module.exports = class bitmax extends Exchange { } const type = this.safeStringLower (order, 'orderType'); const side = this.safeStringLower (order, 'side'); - const feeCost = this.safeFloat (order, 'cumFee'); + const feeCost = this.safeNumber (order, 'cumFee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeAsset'); @@ -1028,8 +986,8 @@ module.exports = class bitmax extends Exchange { 'currency': feeCurrencyCode, }; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1044,14 +1002,14 @@ module.exports = class bitmax extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1088,7 +1046,7 @@ module.exports = class bitmax extends Exchange { request['orderPrice'] = this.priceToPrecision (symbol, price); } if ((type === 'stop_limit') || (type === 'stop_market')) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders'); } else { @@ -1624,7 +1582,7 @@ module.exports = class bitmax extends Exchange { // } // const id = this.safeString (transaction, 'requestId'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const destAddress = this.safeValue (transaction, 'destAddress', {}); const address = this.safeString (destAddress, 'address'); const tag = this.safeString (destAddress, 'destTag'); @@ -1634,7 +1592,7 @@ module.exports = class bitmax extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'commission'); + const feeCost = this.safeNumber (transaction, 'commission'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Exchange.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Exchange.js index eb017b5bf..0cf2c9fb0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Exchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Exchange.js @@ -44,6 +44,7 @@ const { // eslint-disable-line object-curly-newline const { TRUNCATE, ROUND, DECIMAL_PLACES, NO_PADDING } = functions.precisionConstants const BN = require ('../static_dependencies/BN/bn') +const Precise = require ('./Precise') // ---------------------------------------------------------------------------- @@ -224,6 +225,11 @@ module.exports = class Exchange { this.minFundingAddressLength = 1 // used in checkAddress this.substituteCommonCurrencyCodes = true // reserved + this.quoteJsonNumbers = true // treat numbers in json as quoted precise strings + this.number = Number // or String (a pointer to a function) + + // whether fees should be summed by currency code + this.reduceFees = true // do not delete this line, it is needed for users to be able to define their own fetchImplementation this.fetchImplementation = defaultFetch @@ -519,7 +525,7 @@ module.exports = class Exchange { parseJson (jsonString) { try { if (this.isJsonEncodedObject (jsonString)) { - return JSON.parse (jsonString) + return JSON.parse (this.onJsonResponse (jsonString)) } } catch (e) { // SyntaxError @@ -598,7 +604,11 @@ module.exports = class Exchange { } onRestResponse (statusCode, statusText, url, method, responseHeaders, responseBody, requestHeaders, requestBody) { - return responseBody.trim ().replace (/:(\d{15,}),/g, ':"$1",'); + return responseBody.trim () + } + + onJsonResponse (responseBody) { + return this.quoteJsonNumbers ? responseBody.replace (/":([+.0-9eE-]+),/g, '":"$1",') : responseBody; } setMarkets (markets, currencies = undefined) { @@ -918,8 +928,8 @@ module.exports = class Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = parseFloat (bidask[priceKey]) - const amount = parseFloat (bidask[amountKey]) + const price = this.safeNumber (bidask, priceKey) + const amount = this.safeNumber (bidask, amountKey) return [ price, amount ] } @@ -945,7 +955,7 @@ module.exports = class Exchange { } } - parseBalance (balance) { + parseBalance (balance, legacy = true) { const codes = Object.keys (this.omit (balance, [ 'info', 'free', 'used', 'total' ])); @@ -957,20 +967,34 @@ module.exports = class Exchange { const code = codes[i] if (balance[code].total === undefined) { if (balance[code].free !== undefined && balance[code].used !== undefined) { - balance[code].total = this.sum (balance[code].free, balance[code].used) + if (legacy) { + balance[code].total = this.sum (balance[code].free, balance[code].used) + } else { + balance[code].total = Precise.stringAdd (balance[code].free, balance[code].used) + } } } if (balance[code].free === undefined) { if (balance[code].total !== undefined && balance[code].used !== undefined) { - balance[code].free = this.sum (balance[code].total, -balance[code].used) + if (legacy) { + balance[code].free = this.sum (balance[code].total, -balance[code].used) + } else { + balance[code].free = Precise.stringSub (balance[code].total, balance[code].used) + } } } if (balance[code].used === undefined) { if (balance[code].total !== undefined && balance[code].free !== undefined) { - balance[code].used = this.sum (balance[code].total, -balance[code].free) + if (legacy) { + balance[code].used = this.sum (balance[code].total, -balance[code].free) + } else { + balance[code].used = Precise.stringSub (balance[code].total, balance[code].free) + } } } - + balance[code].free = this.parseNumber (balance[code].free) + balance[code].used = this.parseNumber (balance[code].used) + balance[code].total = this.parseNumber (balance[code].total) balance.free[code] = balance[code].free balance.used[code] = balance[code].used balance.total[code] = balance[code].total @@ -979,6 +1003,10 @@ module.exports = class Exchange { return balance } + async fetchBalance (params = {}) { + throw new NotSupported (this.id + ' fetchBalance not supported yet') + } + async fetchPartialBalance (part, params = {}) { const balance = await this.fetchBalance (params) return balance[part] @@ -1088,11 +1116,27 @@ module.exports = class Exchange { return indexed ? indexBy (result, key) : result } + parseTickers (tickers, symbols = undefined) { + const result = []; + for (let i = 0; i < tickers.length; i++) { + result.push (this.parseTicker (tickers[i])); + } + return this.filterByArray (result, 'symbol', symbols); + } + + parseDepositAddresses (addresses, codes = undefined) { + let result = []; + for (let i = 0; i < addresses.length; i++) { + const address = this.parseDepositAddress (addresses[i]); + result.push (address); + } + if (codes) { + result = this.filterByArray (result, 'currency', codes); + } + return this.indexBy (result, 'currency'); + } + parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (trades)) { - // throw new ExchangeError (this.id + ' parseTrades expected an array in the trades argument, but got ' + typeof trades); - // } let result = Object.values (trades || []).map ((trade) => this.extend (this.parseTrade (trade, market), params)) result = sortBy (result, 'timestamp') const symbol = (market !== undefined) ? market['symbol'] : undefined @@ -1101,10 +1145,6 @@ module.exports = class Exchange { } parseTransactions (transactions, currency = undefined, since = undefined, limit = undefined, params = {}) { - // this code is commented out temporarily to catch for exchange-specific errors - // if (!this.isArray (transactions)) { - // throw new ExchangeError (this.id + ' parseTransactions expected an array in the transactions argument, but got ' + typeof transactions); - // } let result = Object.values (transactions || []).map ((transaction) => this.extend (this.parseTransaction (transaction, currency), params)) result = this.sortBy (result, 'timestamp'); const code = (currency !== undefined) ? currency['code'] : undefined; @@ -1112,6 +1152,14 @@ module.exports = class Exchange { return this.filterByCurrencySinceLimit (result, code, since, limit, tail); } + parseTransfers (transfers, currency = undefined, since = undefined, limit = undefined, params = {}) { + let result = Object.values (transfers || []).map ((transfer) => this.extend (this.parseTransfer (transfer, currency), params)) + result = this.sortBy (result, 'timestamp'); + const code = (currency !== undefined) ? currency['code'] : undefined; + const tail = since === undefined; + return this.filterByCurrencySinceLimit (result, code, since, limit, tail); + } + parseLedger (data, currency = undefined, since = undefined, limit = undefined, params = {}) { let result = []; const array = Object.values (data || []); @@ -1256,19 +1304,19 @@ module.exports = class Exchange { return this.createOrder (symbol, ...args) } - createLimitOrder (symbol, side, amount, price = undefined, params = {}) { + createLimitOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'limit', side, amount, price, params) } - createMarketOrder (symbol, side, amount, price = undefined, params = {}) { + createMarketOrder (symbol, side, amount, price, params = {}) { return this.createOrder (symbol, 'market', side, amount, price, params) } - createLimitBuyOrder (symbol, amount, price = undefined, params = {}) { + createLimitBuyOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'buy', amount, price, params) } - createLimitSellOrder (symbol, amount, price = undefined, params = {}) { + createLimitSellOrder (symbol, amount, price, params = {}) { return this.createOrder (symbol, 'limit', 'sell', amount, price, params) } @@ -1301,15 +1349,43 @@ module.exports = class Exchange { } calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol] - const rate = market[takerOrMaker] - const cost = parseFloat (this.costToPrecision (symbol, amount * price)) + const market = this.markets[symbol]; + const feeSide = this.safeString (market, 'feeSide', 'quote'); + let key = 'quote'; + let cost = undefined; + if (feeSide === 'quote') { + // the fee is always in quote currency + cost = amount * price; + } else if (feeSide === 'base') { + // the fee is always in base currency + cost = amount; + } else if (feeSide === 'get') { + // the fee is always in the currency you get + cost = amount; + if (side === 'sell') { + cost *= price; + } else { + key = 'base'; + } + } else if (feeSide === 'give') { + // the fee is always in the currency you give + cost = amount; + if (side === 'buy') { + cost *= price; + } else { + key = 'base'; + } + } + const rate = market[takerOrMaker]; + if (cost !== undefined) { + cost *= rate; + } return { 'type': takerOrMaker, - 'currency': market['quote'], + 'currency': market[key], 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, rate * cost)), - } + 'cost': cost, + }; } checkRequiredDependencies () { @@ -1393,6 +1469,25 @@ module.exports = class Exchange { return new BN (a).pow (new BN (b)) } + reduceFeesByCurrency (fees) { + const reduced = {}; + for (let i = 0; i < fees.length; i++) { + const fee = fees[i]; + const feeCurrencyCode = this.safeValue (fee, 'currency'); + if (feeCurrencyCode !== undefined) { + if (feeCurrencyCode in reduced) { + reduced[feeCurrencyCode]['cost'] = this.sum (reduced[feeCurrencyCode]['cost'], fee['cost']); + } else { + reduced[feeCurrencyCode] = { + 'cost': fee['cost'], + 'currency': feeCurrencyCode, + }; + } + } + } + return Object.values (reduced); + } + safeOrder (order) { // Cost // Remaining @@ -1401,65 +1496,143 @@ module.exports = class Exchange { // Amount // Filled // - // First we try to calculate filled from the trades - const parseFilled = order['filled'] === undefined; - const parseCost = order['cost'] === undefined; - if (parseFilled) { - order['filled'] = 0 - } - if (parseCost) { - order['cost'] = 0 - } - if (parseFilled || parseCost) { - if (Array.isArray (order['trades'])) { - for (let i = 0; i < order['trades'].length; i++) { - const trade = order['trades'][i] - if (parseFilled) { - order['filled'] = this.sum (order['filled'], trade['amount']) + // first we try to calculate the order fields from the trades + let amount = this.safeValue (order, 'amount'); + let remaining = this.safeValue (order, 'remaining'); + let filled = this.safeValue (order, 'filled'); + let cost = this.safeValue (order, 'cost'); + let average = this.safeValue (order, 'average'); + let price = this.safeValue (order, 'price'); + let lastTradeTimeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); + const parseFilled = (filled === undefined); + const parseCost = (cost === undefined); + const parseLastTradeTimeTimestamp = (lastTradeTimeTimestamp === undefined); + const parseFee = this.safeValue (order, 'fee') === undefined; + const parseFees = this.safeValue (order, 'fees') === undefined; + const shouldParseFees = parseFee || parseFees; + const fees = shouldParseFees ? [] : undefined; + if (parseFilled || parseCost || shouldParseFees) { + const trades = this.safeValue (order, 'trades'); + if (trades !== undefined) { + if (parseFilled) { + filled = 0; + } + if (parseCost) { + cost = 0; + } + for (let i = 0; i < trades.length; i++) { + const trade = trades[i]; + const tradeAmount = this.safeValue (trade, 'amount'); + if (parseFilled && (tradeAmount !== undefined)) { + filled = this.sum (filled, tradeAmount); } - if (parseCost) { - order['cost'] = this.sum (order['cost'], trade['cost']) + const tradeCost = this.safeValue (trade, 'cost'); + if (parseCost && (tradeCost !== undefined)) { + cost = this.sum (cost, tradeCost); + } + const tradeTimestamp = this.safeValue (trade, 'timestamp'); + if (parseLastTradeTimeTimestamp && (tradeTimestamp !== undefined)) { + if (lastTradeTimeTimestamp === undefined) { + lastTradeTimeTimestamp = tradeTimestamp; + } else { + lastTradeTimeTimestamp = Math.max (lastTradeTimeTimestamp, tradeTimestamp); + } + } + if (shouldParseFees) { + const tradeFees = this.safeValue (trade, 'fees'); + if (tradeFees !== undefined) { + for (let j = 0; j < tradeFees.length; j++) { + const tradeFee = tradeFees[j]; + fees.push (this.extend ({}, tradeFee)); + } + } else { + const tradeFee = this.safeValue (trade, 'fee'); + if (tradeFee !== undefined) { + fees.push (this.extend ({}, tradeFee)); + } + } } } } } - // We ensure amount = filled + remaining - if (order['amount'] === undefined) { - if (order['filled'] !== undefined && order['remaining'] !== undefined) { - order['amount'] = this.sum (order['filled'], order['remaining']) + if (shouldParseFees) { + const reducedFees = this.reduceFees ? this.reduceFeesByCurrency (fees) : fees; + const reducedLength = reducedFees.length; + if (!parseFee && (reducedLength === 0)) { + reducedFees.push (order['fee']); + } + if (parseFees) { + order['fees'] = reducedFees; + } + if (parseFee && (reducedLength === 1)) { + order['fee'] = reducedFees[0]; } } - if (order['filled'] === undefined) { - if (order['amount'] !== undefined && order['remaining'] !== undefined) { - order['filled'] = Math.max (this.sum (order['amount'], -order['remaining']), 0) + if (amount === undefined) { + // ensure amount = filled + remaining + if (filled !== undefined && remaining !== undefined) { + amount = this.sum (filled, remaining); + } else if (this.safeString (order, 'status') === 'closed') { + amount = filled; } } - if (order['remaining'] === undefined) { - if (order['amount'] !== undefined && order['filled'] !== undefined) { - order['remaining'] = Math.max (this.sum (order['amount'], -order['filled']), 0) + if (filled === undefined) { + if (amount !== undefined && remaining !== undefined) { + filled = Math.max (this.sum (amount, -remaining), 0); } } - // We ensure that the average field is calculated correctly - if (order['average'] === undefined) { - if (order['filled'] !== undefined && order['cost'] !== undefined && order['cost'] > 0) { - order['average'] = order['filled'] / order['cost'] + if (remaining === undefined) { + if (amount !== undefined && filled !== undefined) { + remaining = Math.max (this.sum (amount, -filled), 0); } } - // We also ensure the cost field is calculated correctly - const costPriceExists = (order['average'] !== undefined) || (order['price'] !== undefined) - if ((order['filled'] !== undefined) && costPriceExists) { - let costPrice = undefined; - if (order['average'] === undefined) { - costPrice = order['price'] - } else { - costPrice = order['average'] + // ensure that the average field is calculated correctly + if (average === undefined) { + if ((filled !== undefined) && (cost !== undefined) && (cost > 0)) { + average = cost / filled; } - order['cost'] = costPrice * order['filled'] } - // We add support for market orders - if (order['price'] === undefined && order['type'] === 'market') { - order['price'] = order['average'] + // also ensure the cost field is calculated correctly + const costPriceExists = (average !== undefined) || (price !== undefined); + if (parseCost && (filled !== undefined) && costPriceExists) { + cost = (average === undefined) ? (price * filled) : (average * filled); } - return order + // support for market orders + const orderType = this.safeValue (order, 'type'); + const emptyPrice = (price === undefined) || (price === 0.0); + if (emptyPrice && (orderType === 'market')) { + price = average; + } + return this.extend (order, { + 'lastTradeTimestamp': lastTradeTimeTimestamp, + 'price': price, + 'amount': amount, + 'cost': cost, + 'average': average, + 'filled': filled, + 'remaining': remaining, + }); + } + + parseNumber (value, d = undefined) { + if (value === undefined) { + return d + } else { + try { + return this.number (value) + } catch (e) { + return d + } + } + } + + safeNumber (object, key, d = undefined) { + const value = this.safeString (object, key) + return this.parseNumber (value, d) + } + + safeNumber2 (object, key1, key2, d = undefined) { + const value = this.safeString2 (object, key1, key2) + return this.parseNumber (value, d) } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Precise.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Precise.js new file mode 100644 index 000000000..9bf17ad8d --- /dev/null +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/Precise.js @@ -0,0 +1,145 @@ +'use strict' + +const BN = require ('../static_dependencies/BN/bn') + +class Precise { + constructor (number, decimals = 0) { + const isBN = number instanceof BN + const isString = typeof number === 'string' + if (!(isBN || isString)) { + throw new Error ('Precise initiated with something other than a string or BN') + } + if (isBN) { + this.integer = number + this.decimals = decimals + } else { + if (decimals) { + throw new Error ('Cannot set decimals when initializing with a string') + } + let modifier = 0 + number = number.toLowerCase () + if (number.indexOf ('e') > -1) { + [ number, modifier ] = number.split ('e') + modifier = parseInt (modifier) + } + const decimalIndex = number.indexOf ('.') + this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0 + const integerString = number.replace ('.', '') + this.integer = new BN (integerString) + this.decimals = this.decimals - modifier + } + this.base = 10 + this.reduce () + } + + mul (other) { + // other must be another instance of Precise + const integerResult = this.integer.mul (other.integer) + return new Precise (integerResult, this.decimals + other.decimals) + } + + div (other, precision = 18) { + const distance = precision - this.decimals + other.decimals + let numerator + if (distance === 0) { + numerator = this.integer + } else if (distance < 0) { + const exponent = new BN (this.base).pow (new BN (-distance)) + numerator = this.integer.div (exponent) + } else { + const exponent = new BN (this.base).pow (new BN (distance)) + numerator = this.integer.mul (exponent) + } + const result = numerator.div (other.integer) + return new Precise (result, precision) + } + + add (other) { + if (this.decimals === other.decimals) { + const integerResult = this.integer.add (other.integer) + return new Precise (integerResult, this.decimals) + } else { + const [ smaller, bigger ] = + (this.decimals > other.decimals) ? [ other, this ] : [ this, other ] + const exponent = new BN (bigger.decimals - smaller.decimals) + const normalised = smaller.integer.mul (new BN (this.base).pow (exponent)) + const result = normalised.add (bigger.integer) + return new Precise (result, bigger.decimals) + } + } + + sub (other) { + const negative = new Precise (other.integer.neg (), other.decimals) + return this.add (negative) + } + + reduce () { + const zero = new BN (0) + if (this.integer.eq (zero)) { + this.decimals = 0 + return this + } + const base = new BN (this.base) + let divmod = this.integer.divmod (base) + while (divmod.mod.eq (zero)) { + this.integer = divmod.div + this.decimals-- + divmod = this.integer.divmod (base) + } + return this + } + + toString () { + const sign = this.integer.negative ? '-' : '' + const integerArray = Array.from (this.integer.abs ().toString (this.base).padStart (this.decimals, '0')) + const index = integerArray.length - this.decimals + let item + if (index === 0) { + // if we are adding to the front + item = '0.' + } else if (this.decimals < 0) { + item = '0'.repeat (-this.decimals) + } else if (this.decimals === 0) { + item = '' + } else { + item = '.' + } + integerArray.splice (index, 0, item) + return sign + integerArray.join ('') + } + + static stringMul (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).mul (new Precise (string2)).toString () + } + + static stringDiv (string1, string2, precision = 18) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).div (new Precise (string2), precision).toString () + } + + static stringAdd (string1, string2) { + if ((string1 === undefined) && (string2 === undefined)) { + return undefined + } + if (string1 === undefined) { + return string2 + } else if (string2 === undefined) { + return string1 + } + return (new Precise (string1)).add (new Precise (string2)).toString () + } + + static stringSub (string1, string2) { + if ((string1 === undefined) || (string2 === undefined)) { + return undefined + } + return (new Precise (string1)).sub (new Precise (string2)).toString () + } +} + +module.exports = Precise; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/functions/encode.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/functions/encode.js index 0b4331ccf..e64251dbc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/functions/encode.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/base/functions/encode.js @@ -19,7 +19,6 @@ let base58Encoder = null module.exports = { json: (data, params = undefined) => JSON.stringify (data) - , unjson: JSON.parse , isJsonEncodedObject: object => ( (typeof object === 'string') && diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bibox.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bibox.js index 4d46d8f35..ed9826a1a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bibox.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bibox.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AccountSuspended, ArgumentsRequired, AuthenticationError, DDoSProtection, ExchangeNotAvailable, InvalidOrder, OrderNotFound, PermissionDenied, InsufficientFunds, BadSymbol, RateLimitExceeded, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -229,9 +230,9 @@ module.exports = class bibox extends Exchange { const quote = this.safeCurrencyCode (quoteId); symbol = base + '/' + quote; } - const last = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); - const baseVolume = this.safeFloat2 (ticker, 'vol', 'vol24H'); + const last = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); + const baseVolume = this.safeNumber2 (ticker, 'vol', 'vol24H'); let open = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; @@ -245,11 +246,11 @@ module.exports = class bibox extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -260,7 +261,7 @@ module.exports = class bibox extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': baseVolume, - 'quoteVolume': this.safeFloat (ticker, 'amount'), + 'quoteVolume': this.safeNumber (ticker, 'amount'), 'info': ticker, }; } @@ -276,17 +277,6 @@ module.exports = class bibox extends Exchange { return this.parseTicker (response['result'], market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - const ticker = this.parseTicker (rawTickers[i]); - if ((symbols === undefined) || (this.inArray (ticker['symbol'], symbols))) { - tickers.push (ticker); - } - } - return tickers; - } - async fetchTickers (symbols = undefined, params = {}) { const request = { 'cmd': 'marketAll', @@ -319,7 +309,7 @@ module.exports = class bibox extends Exchange { symbol = market['symbol']; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = this.safeString (trade, 'fee_symbol'); if (feeCurrency !== undefined) { if (feeCurrency in this.currencies_by_id) { @@ -329,12 +319,11 @@ module.exports = class bibox extends Exchange { } } const feeRate = undefined; // todo: deduce from market if market is defined - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if (feeCost !== undefined) { fee = { 'cost': -feeCost, @@ -385,7 +374,7 @@ module.exports = class bibox extends Exchange { request['size'] = limit; // default = 200 } const response = await this.publicGetMdata (this.extend (request, params)); - return this.parseOrderBook (response['result'], this.safeFloat (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); + return this.parseOrderBook (response['result'], this.safeNumber (response['result'], 'update_time'), 'bids', 'asks', 'price', 'volume'); } parseOHLCV (ohlcv, market = undefined) { @@ -401,11 +390,11 @@ module.exports = class bibox extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -497,7 +486,7 @@ module.exports = class bibox extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw_min'), + 'min': this.safeNumber (currency, 'withdraw_min'), 'max': undefined, }, }, @@ -629,19 +618,17 @@ module.exports = class bibox extends Exchange { code = this.currencies_by_id[code]['code']; } const account = this.account (); - let balance = indexed[id]; + const balance = indexed[id]; if (typeof balance === 'string') { - balance = parseFloat (balance); account['free'] = balance; - account['used'] = 0.0; account['total'] = balance; } else { - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -732,8 +719,8 @@ module.exports = class bibox extends Exchange { let tag = this.safeString (transaction, 'addr_remark'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'fee'); if (type === 'deposit') { feeCost = 0; tag = undefined; @@ -841,26 +828,19 @@ module.exports = class bibox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const type = (order['order_type'] === 1) ? 'market' : 'limit'; - const timestamp = order['createdAt']; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'deal_price'); - const filled = this.safeFloat (order, 'deal_amount'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat2 (order, 'deal_money', 'money'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - cost = price * filled; - } - } - const side = (order['order_side'] === 1) ? 'buy' : 'sell'; + const rawType = this.safeString (order, 'order_type'); + const type = (rawType === '1') ? 'market' : 'limit'; + const timestamp = this.safeInteger (order, 'createdAt'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'deal_price'); + const filled = this.safeNumber (order, 'deal_amount'); + const amount = this.safeNumber (order, 'amount'); + const cost = this.safeNumber2 (order, 'deal_money', 'money'); + const rawSide = this.safeString (order, 'order_side'); + const side = (rawSide === '1') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -868,8 +848,7 @@ module.exports = class bibox extends Exchange { 'currency': undefined, }; } - cost = cost ? cost : (parseFloat (price) * filled); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -887,11 +866,11 @@ module.exports = class bibox extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -1059,7 +1038,7 @@ module.exports = class bibox extends Exchange { }; const response = await this.privatePostTransfer (request); info[code] = response; - withdrawFees[code] = this.safeFloat (response['result'], 'withdraw_fee'); + withdrawFees[code] = this.safeNumber (response['result'], 'withdraw_fee'); } return { 'info': info, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bigone.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bigone.js index d6e940c4d..f30eec7a4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bigone.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bigone.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, OrderNotFound, InsufficientFunds, PermissionDenied, BadRequest, RateLimitExceeded, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -260,28 +261,28 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (ticker, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = undefined; - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', {}); const ask = this.safeValue (ticker, 'ask', {}); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (bid, 'price'), - 'bidVolume': this.safeFloat (bid, 'quantity'), - 'ask': this.safeFloat (ask, 'price'), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (bid, 'price'), + 'bidVolume': this.safeNumber (bid, 'quantity'), + 'ask': this.safeNumber (ask, 'price'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, 'last': close, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'daily_change'), + 'change': this.safeNumber (ticker, 'daily_change'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -446,16 +447,13 @@ module.exports = class bigone extends Exchange { // } // const timestamp = this.parse8601 (this.safeString2 (trade, 'created_at', 'inserted_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } let side = this.safeString (trade, 'side'); const takerSide = this.safeString (trade, 'taker_side'); let takerOrMaker = undefined; @@ -529,8 +527,8 @@ module.exports = class bigone extends Exchange { takerCurrencyCode = market['quote']; } } - const makerFeeCost = this.safeFloat (trade, 'maker_fee'); - const takerFeeCost = this.safeFloat (trade, 'taker_fee'); + const makerFeeCost = this.safeNumber (trade, 'maker_fee'); + const takerFeeCost = this.safeNumber (trade, 'taker_fee'); if (makerFeeCost !== undefined) { if (takerFeeCost !== undefined) { result['fees'] = [ @@ -593,11 +591,11 @@ module.exports = class bigone extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -668,11 +666,11 @@ module.exports = class bigone extends Exchange { const symbol = this.safeString (balance, 'asset_symbol'); const code = this.safeCurrencyCode (symbol); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -694,13 +692,9 @@ module.exports = class bigone extends Exchange { const marketId = this.safeString (order, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (amount !== undefined && filled !== undefined) { - remaining = Math.max (0, amount - filled); - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); const status = this.parseOrderStatus (this.safeString (order, 'state')); let side = this.safeString (order, 'side'); if (side === 'BID') { @@ -708,15 +702,9 @@ module.exports = class bigone extends Exchange { } else { side = 'sell'; } - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'updated_at')); - const average = this.safeFloat (order, 'avg_deal_price'); - return { + const average = this.safeNumber (order, 'avg_deal_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -731,14 +719,14 @@ module.exports = class bigone extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -762,7 +750,7 @@ module.exports = class bigone extends Exchange { const isStopLimit = (uppercaseType === 'STOP_LIMIT'); const isStopMarket = (uppercaseType === 'STOP_MARKET'); if (isStopLimit || isStopMarket) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price parameter'); } @@ -1101,7 +1089,7 @@ module.exports = class bigone extends Exchange { const currencyId = this.safeString (transaction, 'asset_symbol'); const code = this.safeCurrencyCode (currencyId); const id = this.safeInteger (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const timestamp = this.parse8601 (this.safeString (transaction, 'inserted_at')); const updated = this.parse8601 (this.safeString2 (transaction, 'updated_at', 'completed_at')); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/binance.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/binance.js index a115b3f7b..a5865c442 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/binance.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/binance.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, RateLimitExceeded, PermissionDenied, NotSupported, BadRequest, BadSymbol, AccountSuspended, OrderImmediatelyFillable } = require ('./base/errors'); -const { ROUND, TRUNCATE } = require ('./base/functions/number'); +const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -47,6 +48,8 @@ module.exports = class binance extends Exchange { 'fetchTransactions': false, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, + 'fetchTransfers': true, }, 'timeframes': { '1m': '1m', @@ -195,6 +198,26 @@ module.exports = class binance extends Exchange { 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/recentRecord', 'apiReferral/kickback/historicalRecord', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccount', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/info', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/recentRecord', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/status', + 'broker/subAccount/depositHist', + 'broker/subAccount/spotSummary', + 'broker/subAccount/marginSummary', + 'broker/subAccount/futuresSummary', + 'broker/rebate/futures/recentRecord', + 'broker/subAccountApi/ipRestriction', + 'broker/universalTransfer', + // v2 not supported yet + // GET /sapi/v2/broker/subAccount/futuresSummary ], 'post': [ 'asset/dust', @@ -234,11 +257,30 @@ module.exports = class binance extends Exchange { // leveraged token endpoints 'blvt/subscribe', 'blvt/redeem', - // broker api + // brokerage API 'apiReferral/customization', 'apiReferral/userCustomization', 'apiReferral/rebate/historicalRecord', 'apiReferral/kickback/historicalRecord', + 'broker/subAccount', + 'broker/subAccount/margin', + 'broker/subAccount/futures', + 'broker/subAccountApi', + 'broker/subAccountApi/permission', + 'broker/subAccountApi/commission', + 'broker/subAccountApi/commission/futures', + 'broker/subAccountApi/commission/coinFutures', + 'broker/transfer', + 'broker/transfer/futures', + 'broker/rebate/historicalRecord', + 'broker/subAccount/bnbBurn/spot', + 'broker/subAccount/bnbBurn/marginInterest', + 'broker/subAccount/blvt', + 'broker/subAccountApi/ipRestriction', + 'broker/subAccountApi/ipRestriction/ipList', + 'broker/universalTransfer', + 'broker/subAccountApi/permission/universalTransfer', + 'broker/subAccountApi/permission/vanillaOptions', ], 'put': [ 'userDataStream', @@ -249,6 +291,9 @@ module.exports = class binance extends Exchange { 'margin/order', 'userDataStream', 'userDataStream/isolated', + // brokerage API + 'broker/subAccountApi', + 'broker/subAccountApi/ipRestriction/ipList', ], }, 'wapi': { @@ -385,6 +430,8 @@ module.exports = class binance extends Exchange { 'positionSide/dual', 'userTrades', 'income', + 'commissionRate', + 'apiTradingStatus', // broker endpoints 'apiReferral/ifNewUser', 'apiReferral/customization', @@ -474,6 +521,7 @@ module.exports = class binance extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.001, @@ -498,7 +546,7 @@ module.exports = class binance extends Exchange { 'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision 'newOrderRespType': { 'market': 'FULL', // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills - 'limit': 'RESULT', // we change it from 'ACK' by default to 'RESULT' + 'limit': 'FULL', // we change it from 'ACK' by default to 'FULL' (returns immediately if limit is not hit) }, 'quoteOrderQty': true, // whether market orders support amounts in quote currency 'broker': { @@ -507,6 +555,25 @@ module.exports = class binance extends Exchange { 'future': 'x-xcKtGhcu', 'delivery': 'x-xcKtGhcu', }, + 'fetchPositions': { + 'future': 'fapiPrivateV2GetAccount', // 'fapiPrivateGetPositionRisk' + 'delivery': 'dapiPrivateGetAccount', // 'dapiPrivateGetPositionRisk' + }, + 'accountsByType': { + 'main': 'MAIN', + 'spot': 'MAIN', + 'margin': 'MARGIN', + 'future': 'UMFUTURE', + 'delivery': 'CMFUTURE', + 'mining': 'MINING', + }, + 'typesByAccount': { + 'MAIN': 'spot', + 'MARGIN': 'margin', + 'UMFUTURE': 'future', + 'CMFUTURE': 'delivery', + 'MINING': 'mining', + }, }, // https://binance-docs.github.io/apidocs/spot/en/#error-codes-2 'exceptions': { @@ -564,6 +631,8 @@ module.exports = class binance extends Exchange { '-3010': ExchangeError, // {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."} '-3022': AccountSuspended, // You account's trading is banned. '-4028': BadRequest, // {"code":-4028,"msg":"Leverage 100 is not valid"} + '-3020': InsufficientFunds, // {"code":-3020,"msg":"Transfer out amount exceeds max amount."} + '-3041': InsufficientFunds, // {"code":-3041,"msg":"Balance is not enough"} '-5013': InsufficientFunds, // Asset transfer failed: insufficient balance" }, }); @@ -706,13 +775,14 @@ module.exports = class binance extends Exchange { let fee = undefined; for (let j = 0; j < networkList.length; j++) { const networkItem = networkList[j]; - const name = this.safeString (networkItem, 'name'); - const withdrawFee = this.safeFloat (networkItem, 'withdrawFee'); + const network = this.safeString (networkItem, 'network'); + // const name = this.safeString (networkItem, 'name'); + const withdrawFee = this.safeNumber (networkItem, 'withdrawFee'); const depositEnable = this.safeValue (networkItem, 'depositEnable'); const withdrawEnable = this.safeValue (networkItem, 'withdrawEnable'); isDepositEnabled = isDepositEnabled || depositEnable; isWithdrawEnabled = isWithdrawEnabled || withdrawEnable; - fees[name] = withdrawFee; + fees[network] = withdrawFee; const isDefault = this.safeValue (networkItem, 'isDefault'); if (isDefault || fee === undefined) { fee = withdrawFee; @@ -898,7 +968,7 @@ module.exports = class binance extends Exchange { if (this.options['adjustForTimeDifference']) { await this.loadTimeDifference (); } - const markets = this.safeValue (response, 'symbols'); + const markets = this.safeValue (response, 'symbols', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -963,10 +1033,10 @@ module.exports = class binance extends Exchange { // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } @@ -977,47 +1047,26 @@ module.exports = class binance extends Exchange { const stepSize = this.safeString (filter, 'stepSize'); entry['precision']['amount'] = this.precisionFromString (stepSize); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat2 (filter, 'minNotional', 'notional'); + entry['limits']['cost']['min'] = this.safeNumber2 (filter, 'minNotional', 'notional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot'); @@ -1188,8 +1237,8 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -1202,13 +1251,13 @@ module.exports = class binance extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['used'] = this.safeFloat (balance, 'initialMargin'); - account['total'] = this.safeFloat2 (balance, 'marginBalance', 'balance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['used'] = this.safeString (balance, 'initialMargin'); + account['total'] = this.safeString2 (balance, 'marginBalance', 'balance'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -1261,36 +1310,36 @@ module.exports = class binance extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'openPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'openPrice'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } async fetchStatus (params = {}) { const response = await this.wapiGetSystemStatus (params); - let status = this.safeValue (response, 'status'); + let status = this.safeString (response, 'status'); if (status !== undefined) { - status = (status === 0) ? 'ok' : 'maintenance'; + status = (status === '0') ? 'ok' : 'maintenance'; this.status = this.extend (this.status, { 'status': status, 'updated': this.milliseconds (), @@ -1319,14 +1368,6 @@ module.exports = class binance extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot'); @@ -1381,11 +1422,11 @@ module.exports = class binance extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -1516,8 +1557,11 @@ module.exports = class binance extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -1535,7 +1579,7 @@ module.exports = class binance extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -1548,10 +1592,6 @@ module.exports = class binance extends Exchange { } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } return { 'info': trade, 'timestamp': timestamp, @@ -1670,7 +1710,7 @@ module.exports = class binance extends Exchange { parseOrder (order, market = undefined) { // - // spot + // spot // // { // "symbol": "LTCBTC", @@ -1691,7 +1731,7 @@ module.exports = class binance extends Exchange { // "isWorking": true // } // - // futures + // futures // // { // "symbol": "BTCUSDT", @@ -1709,6 +1749,33 @@ module.exports = class binance extends Exchange { // "updateTime": 1499827319559 // } // + // createOrder with { "newOrderRespType": "FULL" } + // + // { + // "symbol": "BTCUSDT", + // "orderId": 5403233939, + // "orderListId": -1, + // "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e", + // "transactTime": 1617151923742, + // "price": "0.00000000", + // "origQty": "0.00050000", + // "executedQty": "0.00050000", + // "cummulativeQuoteQty": "29.47081500", + // "status": "FILLED", + // "timeInForce": "GTC", + // "type": "MARKET", + // "side": "BUY", + // "fills": [ + // { + // "price": "58941.63000000", + // "qty": "0.00050000", + // "commission": "0.00007050", + // "commissionAsset": "BNB", + // "tradeId": 737466631 + // } + // ] + // } + // const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -1718,80 +1785,26 @@ module.exports = class binance extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); // - Spot/Margin market: cummulativeQuoteQty // - Futures market: cumQuote. // Note this is not the actual cost, since Binance futures uses leverage to calculate margins. - let cost = this.safeFloat2 (order, 'cummulativeQuoteQty', 'cumQuote'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const cost = this.safeNumber2 (order, 'cummulativeQuoteQty', 'cumQuote'); const id = this.safeString (order, 'orderId'); let type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - if (this.options['parseOrderToPrecision']) { - price = parseFloat (this.priceToPrecision (symbol, price)); - } - } - } - } - } else if (type === 'limit_maker') { + if (type === 'limit_maker') { type = 'limit'; } const side = this.safeStringLower (order, 'side'); - let fee = undefined; - let trades = undefined; - const fills = this.safeValue (order, 'fills'); - if (fills !== undefined) { - trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - if (this.options['parseOrderToPrecision']) { - average = parseFloat (this.priceToPrecision (symbol, average)); - } - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const fills = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (fills, market); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = (type === 'limit_maker') || (timeInForce === 'GTX'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1807,13 +1820,13 @@ module.exports = class binance extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1860,8 +1873,11 @@ module.exports = class binance extends Exchange { } else { request['newClientOrderId'] = clientOrderId; } - if (market['spot']) { + if ((orderType === 'spot') || (orderType === 'margin')) { request['newOrderRespType'] = this.safeValue (this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills + } else { + // delivery and future + request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK" } // additional required fields depending on the order type let timeInForceIsRequired = false; @@ -1891,7 +1907,7 @@ module.exports = class binance extends Exchange { if (uppercaseType === 'MARKET') { const quoteOrderQty = this.safeValue (this.options, 'quoteOrderQty', false); if (quoteOrderQty) { - const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty'); + const quoteOrderQty = this.safeNumber (params, 'quoteOrderQty'); const precision = market['precision']['price']; if (quoteOrderQty !== undefined) { request['quoteOrderQty'] = this.decimalToPrecision (quoteOrderQty, TRUNCATE, precision, this.precisionMode); @@ -1911,7 +1927,7 @@ module.exports = class binance extends Exchange { } else if ((uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT')) { stopPriceIsRequired = true; quantityIsRequired = true; - if (market['future']) { + if (market['future'] || market['delivery']) { priceIsRequired = true; } } else if ((uppercaseType === 'STOP_LOSS_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) { @@ -1934,7 +1950,7 @@ module.exports = class binance extends Exchange { stopPriceIsRequired = true; } else if (uppercaseType === 'TRAILING_STOP_MARKET') { quantityIsRequired = true; - const callbackRate = this.safeFloat (params, 'callbackRate'); + const callbackRate = this.safeNumber (params, 'callbackRate'); if (callbackRate === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a callbackRate extra param for a ' + type + ' order'); } @@ -1952,7 +1968,7 @@ module.exports = class binance extends Exchange { request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -2168,10 +2184,15 @@ module.exports = class binance extends Exchange { } } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.fetchBalance (params); - const info = this.safeValue (response, 'info', {}); + const defaultType = this.safeString (this.options, 'defaultType', 'future'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + const options = this.safeValue (this.options, 'fetchPositions', {}); + const defaultMethod = (type === 'delivery') ? 'dapiPrivateGetAccount' : 'fapiPrivateV2GetAccount'; + const method = this.safeString (options, type, defaultMethod); + const response = await this[method] (params); // // futures, delivery // @@ -2214,9 +2235,44 @@ module.exports = class binance extends Exchange { // ] // } // - const positions = this.safeValue2 (info, 'positions', 'userAssets', []); - // todo unify parsePosition/parsePositions - return positions; + // fapiPrivateGetPositionRisk, dapiPrivateGetPositionRisk + // + // [ + // { + // symbol: 'XRPUSD_210625', + // positionAmt: '0', + // entryPrice: '0.00000000', + // markPrice: '0.00000000', + // unRealizedProfit: '0.00000000', + // liquidationPrice: '0', + // leverage: '20', + // maxQty: '500000', + // marginType: 'cross', + // isolatedMargin: '0.00000000', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0', + // isolatedWallet: '0' + // }, + // { + // symbol: 'BTCUSD_210326', + // positionAmt: '1', + // entryPrice: '60665.79999885', + // markPrice: '60696.76856843', + // unRealizedProfit: '0.00000084', + // liquidationPrice: '58034.68208092', + // leverage: '20', + // maxQty: '50', + // marginType: 'isolated', + // isolatedMargin: '0.00008345', + // isAutoAddMargin: 'false', + // positionSide: 'BOTH', + // notionalValue: '0.00164753', + // isolatedWallet: '0.00008261' + // }, + // ] + // + return this.safeValue (response, 'positions', response); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -2354,7 +2410,7 @@ module.exports = class binance extends Exchange { // const fee = { 'currency': earnedCurrency, - 'cost': this.safeFloat (trade, 'serviceChargeAmount'), + 'cost': this.safeNumber (trade, 'serviceChargeAmount'), }; let symbol = undefined; let amount = undefined; @@ -2362,13 +2418,13 @@ module.exports = class binance extends Exchange { let side = undefined; if (tradedCurrencyIsQuote) { symbol = applicantSymbol; - amount = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); - cost = this.safeFloat (trade, 'amount'); + amount = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); + cost = this.safeNumber (trade, 'amount'); side = 'buy'; } else { symbol = tradedCurrency + '/' + earnedCurrency; - amount = this.safeFloat (trade, 'amount'); - cost = this.sum (this.safeFloat (trade, 'transferedAmount'), fee['cost']); + amount = this.safeNumber (trade, 'amount'); + cost = this.sum (this.safeNumber (trade, 'transferedAmount'), fee['cost']); side = 'sell'; } let price = undefined; @@ -2541,8 +2597,8 @@ module.exports = class binance extends Exchange { } } const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'transactionFee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'transactionFee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -2569,6 +2625,151 @@ module.exports = class binance extends Exchange { }; } + parseTransferStatus (status) { + const statuses = { + 'CONFIRMED': 'ok', + }; + return this.safeString (statuses, status, status); + } + + parseTransfer (transfer, currency = undefined) { + // + // transfer + // + // { + // "tranId":13526853623 + // } + // + // fetchTransfers + // + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // } + // + const id = this.safeString (transfer, 'tranId'); + const currencyId = this.safeString (transfer, 'asset'); + const code = this.safeCurrencyCode (currencyId, currency); + const amount = this.safeNumber (transfer, 'amount'); + const type = this.safeString (transfer, 'type'); + let fromAccount = undefined; + let toAccount = undefined; + const typesByAccount = this.safeValue (this.options, 'typesByAccount', {}); + if (type !== undefined) { + const parts = type.split ('_'); + fromAccount = this.safeValue (parts, 0); + toAccount = this.safeValue (parts, 1); + fromAccount = this.safeString (typesByAccount, fromAccount, fromAccount); + toAccount = this.safeString (typesByAccount, toAccount, toAccount); + } + const timestamp = this.safeInteger (transfer, 'timestamp'); + const status = this.parseTransferStatus (this.safeString (transfer, 'status')); + return { + 'info': transfer, + 'id': id, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'currency': code, + 'amount': amount, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': status, + }; + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount, fromAccount); + const toId = this.safeString (accountsByType, toAccount, toAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'asset': currency['id'], + 'amount': this.currencyToPrecision (code, amount), + 'type': type, + }; + const response = await this.sapiPostAssetTransfer (this.extend (request, params)); + // + // { + // "tranId":13526853623 + // } + // + const transfer = this.parseTransfer (response, currency); + return this.extend (transfer, { + 'amount': amount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + }); + } + + async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const defaultType = this.safeString2 (this.options, 'fetchTransfers', 'defaultType', 'spot'); + const fromAccount = this.safeString (params, 'fromAccount', defaultType); + const defaultTo = (fromAccount === 'future') ? 'spot' : 'future'; + const toAccount = this.safeString (params, 'toAccount', defaultTo); + let type = this.safeString (params, 'type'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + if (type === undefined) { + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fromAccount parameter must be one of ' + keys.join (', ')); + } + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' toAccount parameter must be one of ' + keys.join (', ')); + } + type = fromId + '_' + toId; + } + const request = { + 'type': type, + }; + if (since !== undefined) { + request['startTime'] = since; + } + if (limit !== undefined) { + request['size'] = limit; + } + const response = await this.sapiGetAssetTransfer (this.extend (request, params)); + // + // { + // total: 3, + // rows: [ + // { + // timestamp: 1614640878000, + // asset: 'USDT', + // amount: '25', + // type: 'MAIN_UMFUTURE', + // status: 'CONFIRMED', + // tranId: 43000126248 + // }, + // ] + // } + // + const rows = this.safeValue (response, 'rows', []); + return this.parseTransfers (rows, currency, since, limit); + } + async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -2631,7 +2832,7 @@ module.exports = class binance extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (detail[id], 'withdrawFee'); + withdrawFees[code] = this.safeNumber (detail[id], 'withdrawFee'); } return { 'withdraw': withdrawFees, @@ -2678,8 +2879,8 @@ module.exports = class binance extends Exchange { return { 'info': fee, 'symbol': symbol, - 'maker': this.safeFloat (fee, 'maker'), - 'taker': this.safeFloat (fee, 'taker'), + 'maker': this.safeNumber (fee, 'maker'), + 'taker': this.safeNumber (fee, 'taker'), }; } @@ -2741,7 +2942,6 @@ module.exports = class binance extends Exchange { if (api === 'wapi') { url += '.html'; } - const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); if (path === 'historicalTrades') { if (this.apiKey) { headers = { @@ -2750,19 +2950,22 @@ module.exports = class binance extends Exchange { } else { throw new AuthenticationError (this.id + ' historicalTrades endpoint requires `apiKey` credential'); } - } else if (userDataStream) { + } + const userDataStream = (path === 'userDataStream') || (path === 'listenKey'); + if (userDataStream) { if (this.apiKey) { // v1 special case for userDataStream - body = this.urlencode (params); headers = { 'X-MBX-APIKEY': this.apiKey, 'Content-Type': 'application/x-www-form-urlencoded', }; + if (method !== 'GET') { + body = this.urlencode (params); + } } else { throw new AuthenticationError (this.id + ' userDataStream endpoint requires `apiKey` credential'); } - } - if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { + } else if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'dapiPrivate') || (api === 'fapiPrivate') || (api === 'fapiPrivateV2')) { this.checkRequiredCredentials (); let query = undefined; const recvWindow = this.safeInteger (this.options, 'recvWindow', 5000); @@ -2794,13 +2997,8 @@ module.exports = class binance extends Exchange { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } } else { - // userDataStream endpoints are public, but POST, PUT, DELETE - // therefore they don't accept URL query arguments - // https://github.com/ccxt/ccxt/issues/5224 - if (!userDataStream) { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } + if (Object.keys (params).length) { + url += '?' + this.urlencode (params); } } return { 'url': url, 'method': method, 'body': body, 'headers': headers }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bit2c.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bit2c.js index a4d60733a..1f58d3f75 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bit2c.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bit2c.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, ExchangeError, InvalidNonce, AuthenticationError, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -155,12 +156,12 @@ module.exports = class bit2c extends Exchange { const currencyId = this.currencyId (code); const uppercase = currencyId.toUpperCase (); if (uppercase in balance) { - account['free'] = this.safeFloat (balance, 'AVAILABLE_' + uppercase); - account['total'] = this.safeFloat (balance, uppercase); + account['free'] = this.safeString (balance, 'AVAILABLE_' + uppercase); + account['total'] = this.safeString (balance, uppercase); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -179,22 +180,22 @@ module.exports = class bit2c extends Exchange { }; const ticker = await this.publicGetExchangesPairTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const averagePrice = this.safeFloat (ticker, 'av'); - const baseVolume = this.safeFloat (ticker, 'a'); + const averagePrice = this.safeNumber (ticker, 'av'); + const baseVolume = this.safeNumber (ticker, 'a'); let quoteVolume = undefined; if (baseVolume !== undefined && averagePrice !== undefined) { quoteVolume = baseVolume * averagePrice; } - const last = this.safeFloat (ticker, 'll'); + const last = this.safeNumber (ticker, 'll'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'h'), + 'bid': this.safeNumber (ticker, 'h'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'l'), + 'ask': this.safeNumber (ticker, 'l'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -276,14 +277,8 @@ module.exports = class bit2c extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -296,7 +291,7 @@ module.exports = class bit2c extends Exchange { } const id = this.safeString (order, 'id'); const status = this.safeString (order, 'status'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -313,12 +308,12 @@ module.exports = class bit2c extends Exchange { 'amount': amount, 'filled': undefined, 'remaining': undefined, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -344,16 +339,16 @@ module.exports = class bit2c extends Exchange { parseTrade (trade, market = undefined) { let timestamp = undefined; let id = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let orderId = undefined; let feeCost = undefined; let side = undefined; const reference = this.safeString (trade, 'reference'); if (reference !== undefined) { timestamp = this.safeTimestamp (trade, 'ticks'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'firstAmount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'firstAmount'); const reference_parts = reference.split ('|'); // reference contains 'pair|orderId|tradeId' if (market === undefined) { const marketId = this.safeString (trade, 'pair'); @@ -371,12 +366,12 @@ module.exports = class bit2c extends Exchange { } else if (side === 1) { side = 'sell'; } - feeCost = this.safeFloat (trade, 'feeAmount'); + feeCost = this.safeNumber (trade, 'feeAmount'); } else { timestamp = this.safeTimestamp (trade, 'date'); id = this.safeString (trade, 'tid'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'amount'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'amount'); side = this.safeValue (trade, 'isBid'); if (side !== undefined) { if (side) { @@ -390,6 +385,9 @@ module.exports = class bit2c extends Exchange { if (market !== undefined) { symbol = market['symbol']; } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, @@ -402,7 +400,7 @@ module.exports = class bit2c extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': { 'cost': feeCost, 'currency': 'NIS', diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbank.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbank.js index d357531d7..c3626b01f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbank.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbank.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -78,21 +79,23 @@ module.exports = class bitbank extends Exchange { }, }, 'markets': { + 'BAT/JPY': { 'id': 'bat_jpy', 'symbol': 'BAT/JPY', 'base': 'BAT', 'quote': 'JPY', 'baseId': 'bat', 'quoteId': 'jpy' }, + 'BAT/BTC': { 'id': 'bat_btc', 'symbol': 'BAT/BTC', 'base': 'BAT', 'quote': 'BTC', 'baseId': 'bat', 'quoteId': 'btc' }, 'BCH/BTC': { 'id': 'bcc_btc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'baseId': 'bcc', 'quoteId': 'btc' }, 'BCH/JPY': { 'id': 'bcc_jpy', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bcc', 'quoteId': 'jpy' }, + 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, + 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, + 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, + 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, + 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, 'MONA/BTC': { 'id': 'mona_btc', 'symbol': 'MONA/BTC', 'base': 'MONA', 'quote': 'BTC', 'baseId': 'mona', 'quoteId': 'btc' }, 'MONA/JPY': { 'id': 'mona_jpy', 'symbol': 'MONA/JPY', 'base': 'MONA', 'quote': 'JPY', 'baseId': 'mona', 'quoteId': 'jpy' }, 'QTUM/BTC': { 'id': 'qtum_btc', 'symbol': 'QTUM/BTC', 'base': 'QTUM', 'quote': 'BTC', 'baseId': 'qtum', 'quoteId': 'btc' }, 'QTUM/JPY': { 'id': 'qtum_jpy', 'symbol': 'QTUM/JPY', 'base': 'QTUM', 'quote': 'JPY', 'baseId': 'qtum', 'quoteId': 'jpy' }, - 'ETH/BTC': { 'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'baseId': 'eth', 'quoteId': 'btc' }, - 'LTC/BTC': { 'id': 'ltc_btc', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC', 'baseId': 'ltc', 'quoteId': 'btc' }, - 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, - 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, - 'BTC/JPY': { 'id': 'btc_jpy', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy' }, - 'ETH/JPY': { 'id': 'eth_jpy', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy' }, - 'LTC/JPY': { 'id': 'ltc_jpy', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy' }, - 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, 'XLM/BTC': { 'id': 'xlm_btc', 'symbol': 'XLM/BTC', 'base': 'XLM', 'quote': 'BTC', 'baseId': 'xlm', 'quoteId': 'btc' }, + 'XLM/JPY': { 'id': 'xlm_jpy', 'symbol': 'XLM/JPY', 'base': 'XLM', 'quote': 'JPY', 'baseId': 'xlm', 'quoteId': 'jpy' }, + 'XRP/BTC': { 'id': 'xrp_btc', 'symbol': 'XRP/BTC', 'base': 'XRP', 'quote': 'BTC', 'baseId': 'xrp', 'quoteId': 'btc' }, + 'XRP/JPY': { 'id': 'xrp_jpy', 'symbol': 'XRP/JPY', 'base': 'XRP', 'quote': 'JPY', 'baseId': 'xrp', 'quoteId': 'jpy' }, }, 'fees': { 'trading': { @@ -141,16 +144,16 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -160,7 +163,7 @@ module.exports = class bitbank extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -196,18 +199,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; feeCurrency = market['quote']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'transaction_id', 'trade_id'); const takerOrMaker = this.safeString (trade, 'maker_taker'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee_amount_quote'); + const feeCost = this.safeNumber (trade, 'fee_amount_quote'); if (feeCost !== undefined) { fee = { 'currency': feeCurrency, @@ -259,11 +259,11 @@ module.exports = class bitbank extends Exchange { // return [ this.safeInteger (ohlcv, 5), - this.safeFloat (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), + this.safeNumber (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), ]; } @@ -314,14 +314,13 @@ module.exports = class bitbank extends Exchange { const balance = assets[i]; const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'free_amount'), - 'used': this.safeFloat (balance, 'locked_amount'), - 'total': this.safeFloat (balance, 'onhand_amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'free_amount'); + account['used'] = this.safeString (balance, 'locked_amount'); + account['total'] = this.safeString (balance, 'onhand_amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -346,21 +345,15 @@ module.exports = class bitbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (order, 'ordered_at'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'start_amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const average = this.safeFloat (order, 'average_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'start_amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const average = this.safeNumber (order, 'average_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -374,7 +367,7 @@ module.exports = class bitbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, @@ -382,7 +375,7 @@ module.exports = class bitbank extends Exchange { 'trades': undefined, 'fee': undefined, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbay.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbay.js index 4f502e934..760fc7aa2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbay.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitbay.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -278,8 +279,8 @@ module.exports = class bitbay extends Exchange { if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) { fees = this.safeValue (this.fees, 'fiat', {}); } - const maker = this.safeFloat (fees, 'maker'); - const taker = this.safeFloat (fees, 'taker'); + const maker = this.safeNumber (fees, 'maker'); + const taker = this.safeNumber (fees, 'taker'); // todo: check that the limits have ben interpreted correctly // todo: parse the fees page result.push ({ @@ -295,7 +296,7 @@ module.exports = class bitbay extends Exchange { 'taker': taker, 'limits': { 'amount': { - 'min': this.safeFloat (first, 'minOffer'), + 'min': this.safeNumber (first, 'minOffer'), 'max': undefined, }, 'price': { @@ -303,7 +304,7 @@ module.exports = class bitbay extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (second, 'minOffer'), + 'min': this.safeNumber (second, 'minOffer'), 'max': undefined, }, }, @@ -343,16 +344,10 @@ module.exports = class bitbay extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (order, 'time'); - const amount = this.safeFloat (order, 'startAmount'); - const remaining = this.safeFloat (order, 'currentAmount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } + const amount = this.safeNumber (order, 'startAmount'); + const remaining = this.safeNumber (order, 'currentAmount'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'info': order, @@ -365,16 +360,16 @@ module.exports = class bitbay extends Exchange { 'timeInForce': undefined, 'postOnly': postOnly, 'side': this.safeStringLower (order, 'offerType'), - 'price': this.safeFloat (order, 'rate'), + 'price': this.safeNumber (order, 'rate'), 'stopPrice': undefined, 'amount': amount, 'cost': undefined, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'average': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -427,11 +422,11 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lockedFunds'); - account['free'] = this.safeFloat (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'lockedFunds'); + account['free'] = this.safeString (balance, 'availableFunds'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -450,22 +445,22 @@ module.exports = class bitbay extends Exchange { }; const ticker = await this.publicGetIdTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'volume'); - const vwap = this.safeFloat (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max'), + 'low': this.safeNumber (ticker, 'min'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -474,7 +469,7 @@ module.exports = class bitbay extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), + 'average': this.safeNumber (ticker, 'average'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -775,7 +770,7 @@ module.exports = class bitbay extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const change = this.safeValue (item, 'change', {}); - let amount = this.safeFloat (change, 'total'); + let amount = this.safeNumber (change, 'total'); let direction = 'in'; if (amount < 0) { direction = 'out'; @@ -787,9 +782,9 @@ module.exports = class bitbay extends Exchange { const referenceId = this.safeString (item, 'detailId'); const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const fundsBefore = this.safeValue (item, 'fundsBefore', {}); - const before = this.safeFloat (fundsBefore, 'total'); + const before = this.safeNumber (fundsBefore, 'total'); const fundsAfter = this.safeValue (item, 'fundsAfter', {}); - const after = this.safeFloat (fundsAfter, 'total'); + const after = this.safeNumber (fundsAfter, 'total'); return { 'info': item, 'id': id, @@ -846,11 +841,11 @@ module.exports = class bitbay extends Exchange { const first = this.safeValue (ohlcv, 1, {}); return [ this.safeInteger (ohlcv, 0), - this.safeFloat (first, 'o'), - this.safeFloat (first, 'h'), - this.safeFloat (first, 'l'), - this.safeFloat (first, 'c'), - this.safeFloat (first, 'v'), + this.safeNumber (first, 'o'), + this.safeNumber (first, 'h'), + this.safeNumber (first, 'l'), + this.safeNumber (first, 'c'), + this.safeNumber (first, 'v'), ]; } @@ -933,15 +928,12 @@ module.exports = class bitbay extends Exchange { if (wasTaker !== undefined) { takerOrMaker = wasTaker ? 'taker' : 'maker'; } - const price = this.safeFloat2 (trade, 'rate', 'r'); - const amount = this.safeFloat2 (trade, 'amount', 'a'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'commissionValue'); + const priceString = this.safeString2 (trade, 'rate', 'r'); + const amountString = this.safeString2 (trade, 'amount', 'a'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'commissionValue'); const marketId = this.safeString (trade, 'market'); market = this.safeMarket (marketId, market, '-'); const symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex.js index 6d34687ff..1d7643454 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { NotSupported, RateLimitExceeded, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, InvalidNonce, BadSymbol } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -45,6 +46,7 @@ module.exports = class bitfinex extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': '1m', @@ -158,6 +160,7 @@ module.exports = class bitfinex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': true, 'percentage': true, 'maker': 0.1 / 100, @@ -344,6 +347,8 @@ module.exports = class bitfinex extends Exchange { 'No summary found.': ExchangeError, // fetchTradingFees (summary) endpoint can give this vague error message 'Cannot evaluate your available balance, please try again': ExchangeNotAvailable, 'Unknown symbol': BadSymbol, + 'Cannot complete transfer. Exchange balance insufficient.': InsufficientFunds, + 'Momentary balance check. Please wait few seconds and try the transfer again.': ExchangeError, }, 'broad': { 'Invalid X-BFX-SIGNATURE': AuthenticationError, @@ -441,6 +446,15 @@ module.exports = class bitfinex extends Exchange { 'limit': 'exchange limit', 'market': 'exchange market', }, + 'accountsByType': { + 'spot': 'exchange', + 'margin': 'trading', + 'funding': 'deposit', + 'exchange': 'exchange', + 'trading': 'trading', + 'deposit': 'deposit', + 'derivatives': 'trading', + }, }, }); } @@ -454,7 +468,7 @@ module.exports = class bitfinex extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const code = this.safeCurrencyCode (id); - withdraw[code] = this.safeFloat (fees, id); + withdraw[code] = this.safeNumber (fees, id); } return { 'info': response, @@ -490,14 +504,31 @@ module.exports = class bitfinex extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } async fetchMarkets (params = {}) { const ids = await this.publicGetSymbols (); + // + // [ "btcusd", "ltcusd", "ltcbtc" ] + // const details = await this.publicGetSymbolsDetails (); + // + // [ + // { + // "pair":"btcusd", + // "price_precision":5, + // "initial_margin":"10.0", + // "minimum_margin":"5.0", + // "maximum_order_size":"2000.0", + // "minimum_order_size":"0.0002", + // "expiration":"NA", + // "margin":true + // }, + // ] + // const result = []; for (let i = 0; i < details.length; i++) { const market = details[i]; @@ -528,8 +559,8 @@ module.exports = class bitfinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -540,6 +571,7 @@ module.exports = class bitfinex extends Exchange { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -548,6 +580,8 @@ module.exports = class bitfinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': true, + 'type': 'spot', + 'margin': margin, 'precision': precision, 'limits': limits, 'info': market, @@ -572,40 +606,15 @@ module.exports = class bitfinex extends Exchange { return this.decimalToPrecision (price, TRUNCATE, 8, DECIMAL_PLACES); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - const code = market[key]; - const currency = this.safeValue (this.currencies, code); - if (currency !== undefined) { - const precision = this.safeInteger (currency, 'precision'); - if (precision !== undefined) { - cost = parseFloat (this.currencyToPrecision (code, cost)); - } - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); - const types = { - 'exchange': 'exchange', - 'deposit': 'funding', - 'trading': 'margin', - }; - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } const query = this.omit (params, 'type'); const response = await this.privatePostBalances (query); // [ { type: 'deposit', @@ -621,12 +630,16 @@ module.exports = class bitfinex extends Exchange { // amount: '0.0005', // available: '0.0005' } ], const result = { 'info': response }; + const isDerivative = requestedType === 'derivatives'; for (let i = 0; i < response.length; i++) { const balance = response[i]; const type = this.safeString (balance, 'type'); - const parsedType = this.safeString (types, type); - if ((parsedType === balanceType) || (type === balanceType)) { - const currencyId = this.safeString (balance, 'currency'); + const currencyId = this.safeStringLower (balance, 'currency', ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { const code = this.safeCurrencyCode (currencyId); // bitfinex had BCH previously, now it's BAB, but the old // BCH symbol is kept for backward-compatibility @@ -635,13 +648,80 @@ module.exports = class bitfinex extends Exchange { // https://github.com/ccxt/ccxt/issues/4989 if (!(code in result)) { const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currencyId = this.currencyId (code); + const fromCurrencyId = this.convertDerivativesId (currencyId, fromAccount); + const toCurrencyId = this.convertDerivativesId (currencyId, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'walletfrom': fromId, + 'walletto': toId, + }; + const response = await this.privatePostTransfer (this.extend (request, params)); + // [ + // { + // status: 'success', + // message: '0.0001 Bitcoin transfered from Margin to Exchange' + // } + // ] + const result = this.safeValue (response, 0); + const status = this.safeString (result, 'status'); + const message = this.safeString (result, 'message'); + if (message === undefined) { + throw new ExchangeError (this.id + ' transfer failed'); + } + // [{"status":"error","message":"Momentary balance check. Please wait few seconds and try the transfer again."}] + if (status === 'error') { + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + return { + 'info': response, + 'status': status, + 'amount': requestedAmount, + 'code': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'timestamp': undefined, + 'datetime': undefined, + }; + } + + convertDerivativesId (currencyId, type) { + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if ((type !== 'derivatives' && type !== 'trading' && type !== 'margin') && isDerivativeCode) { + currencyId = currencyId.slice (0, start); + } else if (type === 'derivatives' && !isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + return currencyId; } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -680,7 +760,7 @@ module.exports = class bitfinex extends Exchange { } parseTicker (ticker, market = undefined) { - let timestamp = this.safeFloat (ticker, 'timestamp'); + let timestamp = this.safeNumber (ticker, 'timestamp'); if (timestamp !== undefined) { timestamp *= 1000; } @@ -703,16 +783,16 @@ module.exports = class bitfinex extends Exchange { } } } - const last = this.safeFloat (ticker, 'last_price'); + const last = this.safeNumber (ticker, 'last_price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -721,8 +801,8 @@ module.exports = class bitfinex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'mid'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'mid'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -730,24 +810,21 @@ module.exports = class bitfinex extends Exchange { parseTrade (trade, market) { const id = this.safeString (trade, 'tid'); - let timestamp = this.safeFloat (trade, 'timestamp'); + let timestamp = this.safeNumber (trade, 'timestamp'); if (timestamp !== undefined) { timestamp = parseInt (timestamp) * 1000; } const type = undefined; const side = this.safeStringLower (trade, 'type'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; if ('fee_amount' in trade) { - const feeCost = -this.safeFloat (trade, 'fee_amount'); + const feeCost = -this.safeNumber (trade, 'fee_amount'); const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { @@ -862,6 +939,30 @@ module.exports = class bitfinex extends Exchange { } parseOrder (order, market = undefined) { + // + // { + // id: 57334010955, + // cid: 1611584840966, + // cid_date: null, + // gid: null, + // symbol: 'ltcbtc', + // exchange: null, + // price: '0.0042125', + // avg_execution_price: '0.0042097', + // side: 'sell', + // type: 'exchange market', + // timestamp: '1611584841.0', + // is_live: false, + // is_cancelled: false, + // is_hidden: 0, + // oco_order: 0, + // was_forced: false, + // original_amount: '0.205176', + // remaining_amount: '0.0', + // executed_amount: '0.205176', + // src: 'web' + // } + // const side = this.safeString (order, 'side'); const open = this.safeValue (order, 'is_live'); const canceled = this.safeValue (order, 'is_cancelled'); @@ -873,30 +974,17 @@ module.exports = class bitfinex extends Exchange { } else { status = 'closed'; } - let symbol = undefined; - if (market === undefined) { - const marketId = this.safeStringUpper (order, 'symbol'); - if (marketId !== undefined) { - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - } - } - } - if (market !== undefined) { - symbol = market['symbol']; - } - let orderType = order['type']; + const marketId = this.safeStringUpper (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market); + let orderType = this.safeString (order, 'type', ''); const exchange = orderType.indexOf ('exchange ') >= 0; if (exchange) { const parts = order['type'].split (' '); orderType = parts[1]; } - let timestamp = this.safeFloat (order, 'timestamp'); - if (timestamp !== undefined) { - timestamp = parseInt (timestamp) * 1000; - } + const timestamp = this.safeTimestamp (order, 'timestamp'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -908,17 +996,17 @@ module.exports = class bitfinex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': side, - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_execution_price'), - 'amount': this.safeFloat (order, 'original_amount'), - 'remaining': this.safeFloat (order, 'remaining_amount'), - 'filled': this.safeFloat (order, 'executed_amount'), + 'average': this.safeNumber (order, 'avg_execution_price'), + 'amount': this.safeNumber (order, 'original_amount'), + 'remaining': this.safeNumber (order, 'remaining_amount'), + 'filled': this.safeNumber (order, 'executed_amount'), 'status': status, 'fee': undefined, 'cost': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -973,11 +1061,11 @@ module.exports = class bitfinex extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -1125,11 +1213,11 @@ module.exports = class bitfinex extends Exchange { // "timestamp_created": "1561716066.0" // } // - let timestamp = this.safeFloat (transaction, 'timestamp_created'); + let timestamp = this.safeNumber (transaction, 'timestamp_created'); if (timestamp !== undefined) { timestamp = parseInt (timestamp * 1000); } - let updated = this.safeFloat (transaction, 'timestamp'); + let updated = this.safeNumber (transaction, 'timestamp'); if (updated !== undefined) { updated = parseInt (updated * 1000); } @@ -1137,7 +1225,7 @@ module.exports = class bitfinex extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const type = this.safeStringLower (transaction, 'type'); // DEPOSIT or WITHDRAWAL const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -1150,7 +1238,7 @@ module.exports = class bitfinex extends Exchange { 'address': this.safeString (transaction, 'address'), // todo: this is actually the tag for XRP transfers (the address is missing) 'tag': undefined, // refix it properly for the tag from description 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -1204,7 +1292,7 @@ module.exports = class bitfinex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex2.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex2.js index b47da9faf..9313f2025 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex2.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitfinex2.js @@ -286,6 +286,15 @@ module.exports = class bitfinex2 extends bitfinex { 'JPY': 'JPY', 'GBP': 'GBP', }, + // actually the correct names unlike the v1 + // we don't want to extend this with accountsByType in v1 + 'v2AccountsByType': { + 'spot': 'exchange', + 'exchange': 'exchange', + 'funding': 'funding', + 'margin': 'margin', + 'derivatives': 'margin', + }, }, 'exceptions': { 'exact': { @@ -367,8 +376,8 @@ module.exports = class bitfinex2 extends bitfinex { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -379,6 +388,7 @@ module.exports = class bitfinex2 extends bitfinex { 'min': limits['amount']['min'] * limits['price']['min'], 'max': undefined, }; + const margin = this.safeValue (market, 'margin'); result.push ({ 'id': id, 'symbol': symbol, @@ -393,6 +403,7 @@ module.exports = class bitfinex2 extends bitfinex { 'type': type, 'swap': false, 'spot': spot, + 'margin': margin, 'futures': futures, }); } @@ -505,7 +516,7 @@ module.exports = class bitfinex2 extends bitfinex { const ids = this.safeValue (response, 0, []); const result = {}; for (let i = 0; i < ids.length; i++) { - let id = ids[i]; + const id = ids[i]; const code = this.safeCurrencyCode (id); const label = this.safeValue (indexed['label'], id, []); const name = this.safeString (label, 1); @@ -513,13 +524,14 @@ module.exports = class bitfinex2 extends bitfinex { const type = this.safeString (pool, 1); const feeValues = this.safeValue (indexed['fees'], id, []); const fees = this.safeValue (feeValues, 1, []); - const fee = this.safeFloat (fees, 1); + const fee = this.safeNumber (fees, 1); + const undl = this.safeValue (indexed['undl'], id, []); const precision = 8; // default precision, todo: fix "magic constants" - id = 'f' + id; + const fid = 'f' + id; result[code] = { - 'id': id, + 'id': fid, 'code': code, - 'info': [ id, label, pool, feeValues ], + 'info': [ id, label, pool, feeValues, undl ], 'type': type, 'name': name, 'active': true, @@ -550,40 +562,117 @@ module.exports = class bitfinex2 extends bitfinex { async fetchBalance (params = {}) { // this api call does not return the 'used' amount - use the v1 version instead (which also returns zero balances) + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 await this.loadMarkets (); - const response = await this.privatePostAuthRWallets (params); - const balanceType = this.safeString (params, 'type', 'exchange'); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const requestedType = this.safeString (params, 'type', 'exchange'); + const accountType = this.safeString (accountsByType, requestedType); + if (accountType === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' fetchBalance type parameter must be one of ' + keys.join (', ')); + } + const isDerivative = requestedType === 'derivatives'; + const query = this.omit (params, 'type'); + const response = await this.privatePostAuthRWallets (query); const result = { 'info': response }; - for (let b = 0; b < response.length; b++) { - const balance = response[b]; - const accountType = balance[0]; - let currency = balance[1]; - const total = balance[2]; - const available = balance[4]; - if (accountType === balanceType) { - if (currency[0] === 't') { - currency = currency.slice (1); - } - const code = this.safeCurrencyCode (currency); + for (let i = 0; i < response.length; i++) { + const balance = response[i]; + const type = this.safeString (balance, 0); + const currencyId = this.safeStringLower (balance, 1, ''); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'f0'; + // this will only filter the derivative codes if the requestedType is 'derivatives' + const derivativeCondition = (!isDerivative || isDerivativeCode); + if ((accountType === type) && derivativeCondition) { + const code = this.safeCurrencyCode (currencyId); const account = this.account (); - // do not fill in zeroes and missing values in the parser - // rewrite and unify the following to use the unified parseBalance - account['total'] = total; - if (!available) { - if (available === 0) { - account['free'] = 0; - account['used'] = total; - } else { - account['free'] = total; - } - } else { - account['free'] = available; - account['used'] = account['total'] - account['free']; - } + account['total'] = this.safeString (balance, 2); + account['free'] = this.safeString (balance, 4); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // transferring between derivatives wallet and regular wallet is not documented in their API + // however we support it in CCXT (from just looking at web inspector) + await this.loadMarkets (); + const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsByType, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' transfer toAccount must be one of ' + keys.join (', ')); + } + const currency = this.currency (code); + const fromCurrencyId = this.convertDerivativesId (currency, fromAccount); + const toCurrencyId = this.convertDerivativesId (currency, toAccount); + const requestedAmount = this.currencyToPrecision (code, amount); + // this request is slightly different from v1 fromAccount -> from + const request = { + 'amount': requestedAmount, + 'currency': fromCurrencyId, + 'currency_to': toCurrencyId, + 'from': fromId, + 'to': toId, + }; + const response = await this.privatePostAuthWTransfer (this.extend (request, params)); + // [1616451183763,"acc_tf",null,null,[1616451183763,"exchange","margin",null,"UST","UST",null,1],null,"SUCCESS","1.0 Tether USDt transfered from Exchange to Margin"] + const timestamp = this.safeInteger (response, 0); + // ["error",10001,"Momentary balance check. Please wait few seconds and try the transfer again."] + const error = this.safeString (response, 0); + if (error === 'error') { + const message = this.safeString (response, 2, ''); + // same message as in v1 + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + throw new ExchangeError (this.id + ' ' + message); + } + const info = this.safeValue (response, 4); + const fromResponse = this.safeString (info, 1); + const toResponse = this.safeString (info, 2); + const toCode = this.safeCurrencyCode (this.safeString (info, 5)); + const success = this.safeString (response, 6); + const status = (success === 'SUCCESS') ? 'ok' : undefined; + return { + 'info': response, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'status': status, + 'amount': requestedAmount, + 'code': toCode, + 'fromAccount': fromResponse, + 'toAccount': toResponse, + }; + } + + convertDerivativesId (currency, type) { + // there is a difference between this and the v1 api, namely trading wallet is called margin in v2 + // { + // id: 'fUSTF0', + // code: 'USTF0', + // info: [ 'USTF0', [], [], [], [ 'USTF0', 'UST' ] ], + const info = this.safeValue (currency, 'info'); + const transferId = this.safeString (info, 0); + const underlying = this.safeValue (info, 4, []); + let currencyId = undefined; + if (type === 'derivatives') { + currencyId = this.safeString (underlying, 0, transferId); + const start = currencyId.length - 2; + const isDerivativeCode = currencyId.slice (start) === 'F0'; + if (!isDerivativeCode) { + currencyId = currencyId + 'F0'; + } + } else if (type !== 'margin') { + currencyId = this.safeString (underlying, 1, transferId); + } else { + currencyId = transferId; + } + return currencyId; } async fetchOrder (id, symbol = undefined, params = {}) { @@ -613,9 +702,10 @@ module.exports = class bitfinex2 extends bitfinex { const priceIndex = (fullRequest['precision'] === 'R0') ? 1 : 0; for (let i = 0; i < orderbook.length; i++) { const order = orderbook[i]; - const price = order[priceIndex]; - const amount = Math.abs (order[2]); - const side = (order[2] > 0) ? 'bids' : 'asks'; + const price = this.safeNumber (order, priceIndex); + const signedAmount = this.safeNumber (order, 2); + const amount = Math.abs (signedAmount); + const side = (signedAmount > 0) ? 'bids' : 'asks'; result[side].push ([ price, amount ]); } result['bids'] = this.sortBy (result['bids'], 0, true); @@ -630,26 +720,26 @@ module.exports = class bitfinex2 extends bitfinex { symbol = market['symbol']; } const length = ticker.length; - const last = ticker[length - 4]; + const last = this.safeNumber (ticker, length - 4); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': ticker[length - 2], - 'low': ticker[length - 1], - 'bid': ticker[length - 10], + 'high': this.safeNumber (ticker, length - 2), + 'low': this.safeNumber (ticker, length - 1), + 'bid': this.safeNumber (ticker, length - 10), 'bidVolume': undefined, - 'ask': ticker[length - 8], + 'ask': this.safeNumber (ticker, length - 8), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': ticker[length - 6], - 'percentage': ticker[length - 5] * 100, + 'change': this.safeNumber (ticker, length - 6), + 'percentage': this.safeNumber (ticker, length - 5) * 100, 'average': undefined, - 'baseVolume': ticker[length - 3], + 'baseVolume': this.safeNumber (ticker, length - 3), 'quoteVolume': undefined, 'info': ticker, }; @@ -738,12 +828,12 @@ module.exports = class bitfinex2 extends bitfinex { // const tradeLength = trade.length; const isPrivate = (tradeLength > 5); - const id = trade[0].toString (); + const id = this.safeString (trade, 0); const amountIndex = isPrivate ? 4 : 2; - let amount = trade[amountIndex]; + let amount = this.safeNumber (trade, amountIndex); let cost = undefined; const priceIndex = isPrivate ? 5 : 3; - const price = trade[priceIndex]; + const price = this.safeNumber (trade, priceIndex); let side = undefined; let orderId = undefined; let takerOrMaker = undefined; @@ -751,7 +841,7 @@ module.exports = class bitfinex2 extends bitfinex { let fee = undefined; let symbol = undefined; const timestampIndex = isPrivate ? 2 : 1; - const timestamp = trade[timestampIndex]; + const timestamp = this.safeInteger (trade, timestampIndex); if (isPrivate) { const marketId = trade[1]; if (marketId in this.markets_by_id) { @@ -760,10 +850,12 @@ module.exports = class bitfinex2 extends bitfinex { } else { symbol = this.parseSymbol (marketId); } - orderId = trade[3].toString (); - takerOrMaker = (trade[8] === 1) ? 'maker' : 'taker'; - let feeCost = trade[9]; - const feeCurrency = this.safeCurrencyCode (trade[10]); + orderId = this.safeString (trade, 3); + const maker = this.safeInteger (trade, 8); + takerOrMaker = (maker === 1) ? 'maker' : 'taker'; + let feeCost = this.safeNumber (trade, 9); + const feeCurrencyId = this.safeString (trade, 10); + const feeCurrency = this.safeCurrencyCode (feeCurrencyId); if (feeCost !== undefined) { feeCost = -feeCost; if (symbol in this.markets) { @@ -904,10 +996,10 @@ module.exports = class bitfinex2 extends bitfinex { // https://github.com/ccxt/ccxt/issues/6686 // const timestamp = this.safeTimestamp (order, 5); const timestamp = this.safeInteger (order, 5); - const remaining = Math.abs (this.safeFloat (order, 6)); - const amount = Math.abs (this.safeFloat (order, 7)); - const filled = amount - remaining; - const side = (order[7] < 0) ? 'sell' : 'buy'; + const remaining = Math.abs (this.safeNumber (order, 6)); + const signedAmount = this.safeNumber (order, 7); + const amount = Math.abs (signedAmount); + const side = (signedAmount < 0) ? 'sell' : 'buy'; const orderType = this.safeString (order, 8); const type = this.safeString (this.safeValue (this.options, 'exchangeTypes'), orderType); let status = undefined; @@ -916,11 +1008,10 @@ module.exports = class bitfinex2 extends bitfinex { const parts = statusString.split (' @ '); status = this.parseOrderStatus (this.safeString (parts, 0)); } - const price = this.safeFloat (order, 16); - const average = this.safeFloat (order, 17); - const cost = price * filled; + const price = this.safeNumber (order, 16); + const average = this.safeNumber (order, 17); const clientOrderId = this.safeString (order, 2); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -935,14 +1026,14 @@ module.exports = class bitfinex2 extends bitfinex { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -959,11 +1050,11 @@ module.exports = class bitfinex2 extends bitfinex { if ((orderType === 'LIMIT') || (orderType === 'EXCHANGE LIMIT')) { request['price'] = this.numberToString (price); } else if ((orderType === 'STOP') || (orderType === 'EXCHANGE STOP')) { - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'STOP LIMIT') || (orderType === 'EXCHANGE STOP LIMIT')) { - const priceAuxLimit = this.safeFloat (params, 'price_aux_limit'); - let stopPrice = this.safeFloat (params, 'stopPrice'); + const priceAuxLimit = this.safeNumber (params, 'price_aux_limit'); + let stopPrice = this.safeNumber (params, 'stopPrice'); if (priceAuxLimit === undefined) { if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter or a price_aux_limit parameter for a ' + orderType + ' order'); @@ -978,9 +1069,9 @@ module.exports = class bitfinex2 extends bitfinex { } request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'TRAILING STOP') || (orderType === 'EXCHANGE TRAILING STOP')) { - const priceTrailing = this.safeFloat (params, 'price_trailing'); + const priceTrailing = this.safeNumber (params, 'price_trailing'); request['price_trailing'] = this.numberToString (priceTrailing); - const stopPrice = this.safeFloat (params, 'stopPrice', price); + const stopPrice = this.safeNumber (params, 'stopPrice', price); request['price'] = this.numberToString (stopPrice); } else if ((orderType === 'FOK') || (orderType === 'EXCHANGE FOK') || (orderType === 'IOC') || (orderType === 'EXCHANGE IOC')) { request['price'] = this.numberToString (price); @@ -1312,11 +1403,11 @@ module.exports = class bitfinex2 extends bitfinex { if (currency !== undefined) { code = currency['code']; } - feeCost = this.safeFloat (data, 8); + feeCost = this.safeNumber (data, 8); if (feeCost !== undefined) { feeCost = -feeCost; } - amount = this.safeFloat (data, 5); + amount = this.safeNumber (data, 5); id = this.safeValue (data, 0); status = 'ok'; if (id === 0) { @@ -1330,7 +1421,7 @@ module.exports = class bitfinex2 extends bitfinex { timestamp = this.safeInteger (transaction, 5); updated = this.safeInteger (transaction, 6); status = this.parseTransactionStatus (this.safeString (transaction, 9)); - amount = this.safeFloat (transaction, 12); + amount = this.safeNumber (transaction, 12); if (amount !== undefined) { if (amount < 0) { type = 'withdrawal'; @@ -1338,7 +1429,7 @@ module.exports = class bitfinex2 extends bitfinex { type = 'deposit'; } } - feeCost = this.safeFloat (transaction, 13); + feeCost = this.safeNumber (transaction, 13); if (feeCost !== undefined) { feeCost = -feeCost; } @@ -1466,7 +1557,7 @@ module.exports = class bitfinex2 extends bitfinex { }); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privatePostPositions (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitflyer.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitflyer.js index f9c19b59a..911cb61f0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitflyer.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitflyer.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -185,11 +186,11 @@ module.exports = class bitflyer extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'amount'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -208,16 +209,16 @@ module.exports = class bitflyer extends Exchange { }; const ticker = await this.publicGetGetticker (this.extend (request, params)); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'ltp'); + const last = this.safeNumber (ticker, 'ltp'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'best_bid'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -227,7 +228,7 @@ module.exports = class bitflyer extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_by_product'), + 'baseVolume': this.safeNumber (ticker, 'volume_by_product'), 'quoteVolume': undefined, 'info': ticker, }; @@ -251,14 +252,11 @@ module.exports = class bitflyer extends Exchange { order = this.safeString (trade, 'child_order_acceptance_id'); } const timestamp = this.parse8601 (this.safeString (trade, 'exec_date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -334,18 +332,17 @@ module.exports = class bitflyer extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'child_order_date')); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'outstanding_size'); - const filled = this.safeFloat (order, 'executed_size'); - const price = this.safeFloat (order, 'price'); - const cost = price * filled; + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'outstanding_size'); + const filled = this.safeNumber (order, 'executed_size'); + const price = this.safeNumber (order, 'price'); const status = this.parseOrderStatus (this.safeString (order, 'child_order_state')); const type = this.safeStringLower (order, 'child_order_type'); const side = this.safeStringLower (order, 'side'); const marketId = this.safeString (order, 'product_code'); const symbol = this.safeSymbol (marketId, market); let fee = undefined; - const feeCost = this.safeFloat (order, 'total_commission'); + const feeCost = this.safeNumber (order, 'total_commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -354,7 +351,7 @@ module.exports = class bitflyer extends Exchange { }; } const id = this.safeString (order, 'child_order_acceptance_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -369,14 +366,14 @@ module.exports = class bitflyer extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) { @@ -439,7 +436,7 @@ module.exports = class bitflyer extends Exchange { return this.parseTrades (response, market, since, limit); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { if (symbols === undefined) { throw new ArgumentsRequired (this.id + ' fetchPositions() requires a `symbols` argument, exactly one symbol in an array'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitforex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitforex.js index 8fa337979..0dfebbef7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitforex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitforex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, OrderNotFound, InsufficientFunds, DDoSProtection, PermissionDenied, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -259,7 +260,7 @@ module.exports = class bitforex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -295,14 +296,11 @@ module.exports = class bitforex extends Exchange { const timestamp = this.safeInteger (trade, 'time'); const id = this.safeString (trade, 'tid'); const orderId = undefined; - const amount = this.safeFloat (trade, 'amount'); - const price = this.safeFloat (trade, 'price'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const sideId = this.safeInteger (trade, 'direction'); const side = this.parseSide (sideId); return { @@ -345,12 +343,12 @@ module.exports = class bitforex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'active'); - account['total'] = this.safeFloat (balance, 'fix'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'active'); + account['total'] = this.safeString (balance, 'fix'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTicker (symbol, params = {}) { @@ -366,21 +364,21 @@ module.exports = class bitforex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (data, 'high'), - 'low': this.safeFloat (data, 'low'), - 'bid': this.safeFloat (data, 'buy'), + 'high': this.safeNumber (data, 'high'), + 'low': this.safeNumber (data, 'low'), + 'bid': this.safeNumber (data, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (data, 'sell'), + 'ask': this.safeNumber (data, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (data, 'last'), - 'last': this.safeFloat (data, 'last'), + 'close': this.safeNumber (data, 'last'), + 'last': this.safeNumber (data, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (data, 'vol'), + 'baseVolume': this.safeNumber (data, 'vol'), 'quoteVolume': undefined, 'info': response, }; @@ -400,11 +398,11 @@ module.exports = class bitforex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'vol'), ]; } @@ -472,26 +470,24 @@ module.exports = class bitforex extends Exchange { parseOrder (order, market = undefined) { const id = this.safeString (order, 'orderId'); - const timestamp = this.safeFloat (order, 'createTime'); - const lastTradeTimestamp = this.safeFloat (order, 'lastTime'); + const timestamp = this.safeNumber (order, 'createTime'); + const lastTradeTimestamp = this.safeNumber (order, 'lastTime'); const symbol = market['symbol']; const sideId = this.safeInteger (order, 'tradeType'); const side = this.parseSide (sideId); const type = undefined; - const price = this.safeFloat (order, 'orderPrice'); - const average = this.safeFloat (order, 'avgPrice'); - const amount = this.safeFloat (order, 'orderAmount'); - const filled = this.safeFloat (order, 'dealAmount'); - const remaining = amount - filled; + const price = this.safeNumber (order, 'orderPrice'); + const average = this.safeNumber (order, 'avgPrice'); + const amount = this.safeNumber (order, 'orderAmount'); + const filled = this.safeNumber (order, 'dealAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderState')); - const cost = filled * price; const feeSide = (side === 'buy') ? 'base' : 'quote'; const feeCurrency = market[feeSide]; const fee = { - 'cost': this.safeFloat (order, 'tradeFee'), + 'cost': this.safeNumber (order, 'tradeFee'), 'currency': feeCurrency, }; - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -505,16 +501,15 @@ module.exports = class bitforex extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitget.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitget.js index 3c9581955..75e458fe0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitget.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitget.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -793,7 +794,7 @@ module.exports = class bitget extends Exchange { let swap = false; const baseId = this.safeString2 (market, 'base_currency', 'coin'); const quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { marketType = 'swap'; spot = false; @@ -811,7 +812,7 @@ module.exports = class bitget extends Exchange { 'amount': parseFloat ('1e-' + sizeIncrement), 'price': parseFloat ('1e-' + tickSize), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const status = this.safeString (market, 'status'); let active = undefined; if (status !== undefined) { @@ -1068,26 +1069,26 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat2 (ticker, 'last', 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'last', 'close'); + const open = this.safeNumber (ticker, 'open'); let bidVolume = undefined; let askVolume = undefined; let bid = this.safeValue (ticker, 'bid'); if (bid === undefined) { - bid = this.safeFloat (ticker, 'best_bid'); + bid = this.safeNumber (ticker, 'best_bid'); } else { - bidVolume = this.safeFloat (bid, 1); - bid = this.safeFloat (bid, 0); + bidVolume = this.safeNumber (bid, 1); + bid = this.safeNumber (bid, 0); } let ask = this.safeValue (ticker, 'ask'); if (ask === undefined) { - ask = this.safeFloat (ticker, 'best_ask'); + ask = this.safeNumber (ticker, 'best_ask'); } else { - askVolume = this.safeFloat (ask, 1); - ask = this.safeFloat (ask, 0); + askVolume = this.safeNumber (ask, 1); + ask = this.safeNumber (ask, 0); } - const baseVolume = this.safeFloat2 (ticker, 'amount', 'volume_24h'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber2 (ticker, 'amount', 'volume_24h'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; @@ -1101,8 +1102,8 @@ module.exports = class bitget extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -1337,9 +1338,12 @@ module.exports = class bitget extends Exchange { } let timestamp = this.safeInteger (trade, 'created_at'); timestamp = this.safeInteger2 (trade, 'timestamp', 'ts', timestamp); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'filled_amount', 'order_qty'); - amount = this.safeFloat2 (trade, 'size', 'amount', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'filled_amount', 'order_qty'); + amountString = this.safeString2 (trade, 'size', 'amount', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -1358,18 +1362,13 @@ module.exports = class bitget extends Exchange { type = this.parseOrderType (side); side = this.parseOrderSide (side); } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - let feeCost = this.safeFloat (trade, 'fee'); - if (feeCost === undefined) { - feeCost = this.safeFloat (trade, 'filled_fees'); + let feeCostString = this.safeString (trade, 'fee'); + if (feeCostString === undefined) { + feeCostString = this.safeString (trade, 'filled_fees'); } else { - feeCost = -feeCost; + feeCostString = (feeCostString[0] === '-') ? feeCostString.slice (1) : feeCostString; } + const feeCost = this.parseNumber (feeCostString); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -1492,23 +1491,23 @@ module.exports = class bitget extends Exchange { const volumeIndex = this.safeString (volume, market['type'], 'amount'); return [ this.safeInteger (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, bitget will return base volume in the 7th element for future markets ]; } else { const volumeIndex = this.safeValue (volume, market['type'], 6); return [ this.safeInteger (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, volumeIndex), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, volumeIndex), // Base Volume ]; } } @@ -1610,13 +1609,13 @@ module.exports = class bitget extends Exchange { } const type = this.safeValue (balance, 'type'); if (type === 'trade') { - result[code]['free'] = this.safeFloat (balance, 'balance'); + result[code]['free'] = this.safeString (balance, 'balance'); } else if ((type === 'frozen') || (type === 'lock')) { - const used = this.safeFloat (result[code], 'used'); - result[code]['used'] = this.sum (used, this.safeFloat (balance, 'balance')); + const used = this.safeString (result[code], 'used'); + result[code]['used'] = Precise.stringAdd (used, this.safeString (balance, 'balance')); } } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseSwapBalance (response) { @@ -1640,11 +1639,11 @@ module.exports = class bitget extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeString (balance, 'equity'); + account['free'] = this.safeString (balance, 'total_avail_balance'); result[symbol] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchAccounts (params = {}) { @@ -1921,26 +1920,13 @@ module.exports = class bitget extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let amount = this.safeFloat2 (order, 'amount', 'size'); - const filled = this.safeFloat2 (order, 'filled_amount', 'filled_qty'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - amount = Math.max (amount, filled); - remaining = Math.max (0, amount - filled); - } - } - if (type === 'market') { - remaining = 0; - } - const cost = this.safeFloat (order, 'filled_cash_amount'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); - if ((average === undefined) && (filled !== undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } + const amount = this.safeNumber2 (order, 'amount', 'size'); + const filled = this.safeNumber2 (order, 'filled_amount', 'filled_qty'); + const cost = this.safeNumber (order, 'filled_cash_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'price_avg'); const status = this.parseOrderStatus (this.safeString2 (order, 'state', 'status')); - const feeCost = this.safeFloat2 (order, 'filled_fees', 'fee'); + const feeCost = this.safeNumber2 (order, 'filled_fees', 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -1950,7 +1936,7 @@ module.exports = class bitget extends Exchange { }; } const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1968,11 +1954,11 @@ module.exports = class bitget extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -2019,7 +2005,7 @@ module.exports = class bitget extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'amount'); + let cost = this.safeNumber (params, 'amount'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2569,12 +2555,12 @@ module.exports = class bitget extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const txid = this.safeString (transaction, 'tx_hash'); const timestamp = this.safeInteger (transaction, 'created_at'); const updated = this.safeInteger (transaction, 'updated_at'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -2764,7 +2750,7 @@ module.exports = class bitget extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.swapGetPositionAllPosition (params); // diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bithumb.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bithumb.js index ef4e7d479..051562718 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bithumb.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bithumb.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); const { DECIMAL_PLACES, SIGNIFICANT_DIGITS, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -198,12 +199,12 @@ module.exports = class bithumb extends Exchange { const account = this.account (); const currency = this.currency (code); const lowerCurrencyId = this.safeStringLower (currency, 'id'); - account['total'] = this.safeFloat (balances, 'total_' + lowerCurrencyId); - account['used'] = this.safeFloat (balances, 'in_use_' + lowerCurrencyId); - account['free'] = this.safeFloat (balances, 'available_' + lowerCurrencyId); + account['total'] = this.safeString (balances, 'total_' + lowerCurrencyId); + account['used'] = this.safeString (balances, 'in_use_' + lowerCurrencyId); + account['free'] = this.safeString (balances, 'available_' + lowerCurrencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -265,8 +266,8 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const open = this.safeFloat (ticker, 'opening_price'); - const close = this.safeFloat (ticker, 'closing_price'); + const open = this.safeNumber (ticker, 'opening_price'); + const close = this.safeNumber (ticker, 'closing_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -277,18 +278,18 @@ module.exports = class bithumb extends Exchange { } average = this.sum (open, close) / 2; } - const baseVolume = this.safeFloat (ticker, 'units_traded_24H'); - const quoteVolume = this.safeFloat (ticker, 'acc_trade_value_24H'); + const baseVolume = this.safeNumber (ticker, 'units_traded_24H'); + const quoteVolume = this.safeNumber (ticker, 'acc_trade_value_24H'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -394,11 +395,11 @@ module.exports = class bithumb extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -488,18 +489,16 @@ module.exports = class bithumb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'units_traded', 'units'); - let cost = this.safeFloat (trade, 'total'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'units_traded', 'units'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId); @@ -702,14 +701,14 @@ module.exports = class bithumb extends Exchange { const sideProperty = this.safeValue2 (order, 'type', 'side'); const side = (sideProperty === 'bid') ? 'buy' : 'sell'; const status = this.parseOrderStatus (this.safeString (order, 'order_status')); - let price = this.safeFloat2 (order, 'order_price', 'price'); + let price = this.safeNumber2 (order, 'order_price', 'price'); let type = 'limit'; if (price === 0) { price = undefined; type = 'market'; } - const amount = this.safeFloat2 (order, 'order_qty', 'units'); - let remaining = this.safeFloat (order, 'units_remaining'); + const amount = this.safeNumber2 (order, 'order_qty', 'units'); + let remaining = this.safeNumber (order, 'units_remaining'); if (remaining === undefined) { if (status === 'closed') { remaining = 0; @@ -728,65 +727,14 @@ module.exports = class bithumb extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let filled = undefined; - let cost = undefined; - let average = undefined; const id = this.safeString (order, 'order_id'); - const rawTrades = this.safeValue (order, 'contract'); - let trades = undefined; - let fee = undefined; - let fees = undefined; - let feesByCurrency = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'side': side, - 'symbol': symbol, - 'order': id, - }); - filled = 0; - feesByCurrency = {}; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - filled = this.sum (filled, trade['amount']); - cost = this.sum (cost, trade['cost']); - const tradeFee = trade['fee']; - const feeCurrency = tradeFee['currency']; - if (feeCurrency in feesByCurrency) { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': this.sum (feesByCurrency[feeCurrency]['cost'], tradeFee['cost']), - }; - } else { - feesByCurrency[feeCurrency] = { - 'currency': feeCurrency, - 'cost': tradeFee['cost'], - }; - } - } - const feeCurrencies = Object.keys (feesByCurrency); - const feeCurrenciesLength = feeCurrencies.length; - if (feeCurrenciesLength > 1) { - fees = []; - for (let i = 0; i < feeCurrencies.length; i++) { - const feeCurrency = feeCurrencies[i]; - fees.push (feesByCurrency[feeCurrency]); - } - } else { - fee = this.safeValue (feesByCurrency, feeCurrencies[0]); - } - if (filled !== 0) { - average = cost / filled; - } - } - if (amount !== undefined) { - if ((filled === undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if ((remaining === undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const result = { + const rawTrades = this.safeValue (order, 'contract', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'side': side, + 'symbol': symbol, + 'order': id, + }); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -801,20 +749,14 @@ module.exports = class bithumb extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'average': average, - 'filled': filled, + 'cost': undefined, + 'average': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': trades, - }; - if (fee !== undefined) { - result['fee'] = fee; - } else if (fees !== undefined) { - result['fees'] = fees; - } - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmart.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmart.js index 4ad47118a..9ec806c6e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmart.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmart.js @@ -435,16 +435,16 @@ module.exports = class bitmart extends Exchange { // const pricePrecision = this.safeInteger (market, 'price_max_precision'); const precision = { - 'amount': this.safeFloat (market, 'base_min_size'), + 'amount': this.safeNumber (market, 'base_min_size'), 'price': parseFloat (this.decimalToPrecision (Math.pow (10, -pricePrecision), ROUND, 10)), }; - const minBuyCost = this.safeFloat (market, 'min_buy_amount'); - const minSellCost = this.safeFloat (market, 'min_sell_amount'); + const minBuyCost = this.safeNumber (market, 'min_buy_amount'); + const minSellCost = this.safeNumber (market, 'min_sell_amount'); const minCost = Math.max (minBuyCost, minSellCost); const limits = { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': { 'min': undefined, @@ -554,16 +554,16 @@ module.exports = class bitmart extends Exchange { // // the docs are wrong: https://github.com/ccxt/ccxt/issues/5612 // - const amountPrecision = this.safeFloat (contract, 'vol_unit'); - const pricePrecision = this.safeFloat (contract, 'price_unit'); + const amountPrecision = this.safeNumber (contract, 'vol_unit'); + const pricePrecision = this.safeNumber (contract, 'price_unit'); const precision = { 'amount': amountPrecision, 'price': pricePrecision, }; const limits = { 'amount': { - 'min': this.safeFloat (contract, 'min_vol'), - 'max': this.safeFloat (contract, 'max_vol'), + 'min': this.safeNumber (contract, 'min_vol'), + 'max': this.safeNumber (contract, 'max_vol'), }, 'price': { 'min': undefined, @@ -586,8 +586,8 @@ module.exports = class bitmart extends Exchange { future = true; } const feeConfig = this.safeValue (market, 'fee_config', {}); - const maker = this.safeFloat (feeConfig, 'maker_fee'); - const taker = this.safeFloat (feeConfig, 'taker_fee'); + const maker = this.safeNumber (feeConfig, 'maker_fee'); + const taker = this.safeNumber (feeConfig, 'taker_fee'); result.push ({ 'id': id, 'numericId': numericId, @@ -675,33 +675,33 @@ module.exports = class bitmart extends Exchange { const timestamp = this.safeTimestamp (ticker, 'timestamp', this.milliseconds ()); const marketId = this.safeString2 (ticker, 'symbol', 'contract_id'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat2 (ticker, 'close_24h', 'last_price'); - let percentage = this.safeFloat (ticker, 'fluctuation', 'rise_fall_rate'); + const last = this.safeNumber2 (ticker, 'close_24h', 'last_price'); + let percentage = this.safeNumber (ticker, 'fluctuation', 'rise_fall_rate'); if (percentage !== undefined) { percentage *= 100; } - const baseVolume = this.safeFloat2 (ticker, 'base_volume_24h', 'base_coin_volume'); - const quoteVolume = this.safeFloat2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); + const baseVolume = this.safeNumber2 (ticker, 'base_volume_24h', 'base_coin_volume'); + const quoteVolume = this.safeNumber2 (ticker, 'quote_volume_24h', 'quote_coin_volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const open = this.safeFloat2 (ticker, 'open_24h', 'open'); + const open = this.safeNumber2 (ticker, 'open_24h', 'open'); let average = undefined; if ((last !== undefined) && (open !== undefined)) { average = this.sum (last, open) / 2; } - average = this.safeFloat (ticker, 'avg_price', average); + average = this.safeNumber (ticker, 'avg_price', average); const price = this.safeValue (ticker, 'depth_price', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high', 'high_24h'), - 'low': this.safeFloat2 (ticker, 'low', 'low_24h'), - 'bid': this.safeFloat (price, 'best_bid', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (price, 'best_ask', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber2 (ticker, 'high', 'high_24h'), + 'low': this.safeNumber2 (ticker, 'low', 'low_24h'), + 'bid': this.safeNumber (price, 'best_bid', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (price, 'best_ask', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open_24h'), + 'open': this.safeNumber (ticker, 'open_24h'), 'close': last, 'last': last, 'previousClose': undefined, @@ -1005,18 +1005,18 @@ module.exports = class bitmart extends Exchange { if (execType !== undefined) { takerOrMaker = (execType === 'M') ? 'maker' : 'taker'; } - let price = this.safeFloat2 (trade, 'price', 'deal_price'); - price = this.safeFloat (trade, 'price_avg', price); - let amount = this.safeFloat2 (trade, 'amount', 'deal_vol'); - amount = this.safeFloat (trade, 'size', amount); - let cost = this.safeFloat2 (trade, 'count', 'notional'); + let price = this.safeNumber2 (trade, 'price', 'deal_price'); + price = this.safeNumber (trade, 'price_avg', price); + let amount = this.safeNumber2 (trade, 'amount', 'deal_vol'); + amount = this.safeNumber (trade, 'size', amount); + let cost = this.safeNumber2 (trade, 'count', 'notional'); if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { cost = amount * price; } const orderId = this.safeInteger (trade, 'order_id'); const marketId = this.safeString2 (trade, 'contract_id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (trade, 'fees'); + const feeCost = this.safeNumber (trade, 'fees'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_coin_name'); @@ -1144,11 +1144,11 @@ module.exports = class bitmart extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1475,11 +1475,11 @@ module.exports = class bitmart extends Exchange { currencyId = this.safeString (balance, 'coind_code', currencyId); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat2 (balance, 'available', 'available_vol'); - account['used'] = this.safeFloat2 (balance, 'frozen', 'freeze_vol'); + account['free'] = this.safeString2 (balance, 'available', 'available_vol'); + account['used'] = this.safeString2 (balance, 'frozen', 'freeze_vol'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -1548,29 +1548,10 @@ module.exports = class bitmart extends Exchange { if (market !== undefined) { status = this.parseOrderStatusByType (market['type'], this.safeString (order, 'status')); } - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat2 (order, 'price_avg', 'done_avg_price'); - const amount = this.safeFloat2 (order, 'size', 'vol'); - let cost = undefined; - let filled = this.safeFloat2 (order, 'filled_size', 'done_vol'); - let remaining = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - if (filled === undefined) { - filled = Math.max (0, amount - remaining); - } - } - if (filled !== undefined) { - if (remaining === undefined) { - remaining = Math.max (0, amount - filled); - } - if (cost === undefined) { - if (average !== undefined) { - cost = average * filled; - } - } - } - } + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber2 (order, 'price_avg', 'done_avg_price'); + const amount = this.safeNumber2 (order, 'size', 'vol'); + const filled = this.safeNumber2 (order, 'filled_size', 'done_vol'); let side = this.safeString (order, 'side'); // 1 = Open long // 2 = Close short @@ -1592,7 +1573,7 @@ module.exports = class bitmart extends Exchange { average = undefined; } } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -1607,14 +1588,14 @@ module.exports = class bitmart extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatusByType (type, status) { @@ -1655,7 +1636,7 @@ module.exports = class bitmart extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2241,12 +2222,12 @@ module.exports = class bitmart extends Exchange { type = 'deposit'; id = depositId; } - const amount = this.safeFloat (transaction, 'arrival_amount'); + const amount = this.safeNumber (transaction, 'arrival_amount'); const timestamp = this.safeInteger (transaction, 'tapply_timeime'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmex.js index 4f5a0552a..8eddc8287 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitmex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, BadRequest, DDoSProtection, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -215,8 +216,8 @@ module.exports = class bitmex extends Exchange { 'amount': undefined, 'price': undefined, }; - const lotSize = this.safeFloat (market, 'lotSize'); - const tickSize = this.safeFloat (market, 'tickSize'); + const lotSize = this.safeNumber (market, 'lotSize'); + const tickSize = this.safeNumber (market, 'tickSize'); if (lotSize !== undefined) { precision['amount'] = lotSize; } @@ -230,7 +231,7 @@ module.exports = class bitmex extends Exchange { }, 'price': { 'min': tickSize, - 'max': this.safeFloat (market, 'maxPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { 'min': undefined, @@ -240,7 +241,7 @@ module.exports = class bitmex extends Exchange { const limitField = (position === quote) ? 'cost' : 'amount'; limits[limitField] = { 'min': lotSize, - 'max': this.safeFloat (market, 'maxOrderQty'), + 'max': this.safeNumber (market, 'maxOrderQty'), }; result.push ({ 'id': id, @@ -252,8 +253,8 @@ module.exports = class bitmex extends Exchange { 'active': active, 'precision': precision, 'limits': limits, - 'taker': this.safeFloat (market, 'takerFee'), - 'maker': this.safeFloat (market, 'makerFee'), + 'taker': this.safeNumber (market, 'takerFee'), + 'maker': this.safeNumber (market, 'makerFee'), 'type': type, 'spot': false, 'swap': swap, @@ -319,21 +320,17 @@ module.exports = class bitmex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - let free = this.safeFloat (balance, 'availableMargin'); - let total = this.safeFloat (balance, 'marginBalance'); + let free = this.safeString (balance, 'availableMargin'); + let total = this.safeString (balance, 'marginBalance'); if (code === 'BTC') { - if (free !== undefined) { - free /= 100000000; - } - if (total !== undefined) { - total /= 100000000; - } + free = Precise.stringDiv (free, '1e8'); + total = Precise.stringDiv (total, '1e8'); } account['free'] = free; account['total'] = total; result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -412,8 +409,8 @@ module.exports = class bitmex extends Exchange { for (let i = 0; i < response.length; i++) { const order = response[i]; const side = (order['side'] === 'Sell') ? 'asks' : 'bids'; - const amount = this.safeFloat (order, 'size'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const price = this.safeNumber (order, 'price'); // https://github.com/ccxt/ccxt/issues/4926 // https://github.com/ccxt/ccxt/issues/4927 // the exchange sometimes returns null price in the orderbook @@ -619,7 +616,7 @@ module.exports = class bitmex extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'transactType')); const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount !== undefined) { amount = amount / 100000000; } @@ -630,7 +627,7 @@ module.exports = class bitmex extends Exchange { // for unrealized pnl and other transactions without a timestamp timestamp = 0; // see comments above } - let feeCost = this.safeFloat (item, 'fee', 0); + let feeCost = this.safeNumber (item, 'fee', 0); if (feeCost !== undefined) { feeCost = feeCost / 100000000; } @@ -638,7 +635,7 @@ module.exports = class bitmex extends Exchange { 'cost': feeCost, 'currency': code, }; - let after = this.safeFloat (item, 'walletBalance'); + let after = this.safeNumber (item, 'walletBalance'); if (after !== undefined) { after = after / 100000000; } @@ -957,8 +954,8 @@ module.exports = class bitmex extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const open = this.safeFloat (ticker, 'prevPrice24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'prevPrice24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; if (last !== undefined && open !== undefined) { @@ -971,13 +968,13 @@ module.exports = class bitmex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askPrice'), + 'ask': this.safeNumber (ticker, 'askPrice'), 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'vwap'), + 'vwap': this.safeNumber (ticker, 'vwap'), 'open': open, 'close': last, 'last': last, @@ -985,8 +982,8 @@ module.exports = class bitmex extends Exchange { 'change': change, 'percentage': percentage, 'average': this.sum (open, last) / 2, - 'baseVolume': this.safeFloat (ticker, 'homeNotional24h'), - 'quoteVolume': this.safeFloat (ticker, 'foreignNotional24h'), + 'baseVolume': this.safeNumber (ticker, 'homeNotional24h'), + 'quoteVolume': this.safeNumber (ticker, 'foreignNotional24h'), 'info': ticker, }; } @@ -1011,11 +1008,11 @@ module.exports = class bitmex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1144,23 +1141,23 @@ module.exports = class bitmex extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat2 (trade, 'avgPx', 'price'); - const amount = this.safeFloat2 (trade, 'size', 'lastQty'); + const price = this.safeNumber2 (trade, 'avgPx', 'price'); + const amount = this.safeNumber2 (trade, 'size', 'lastQty'); const id = this.safeString (trade, 'trdMatchID'); const order = this.safeString (trade, 'orderID'); const side = this.safeStringLower (trade, 'side'); // price * amount doesn't work for all symbols (e.g. XBT, ETH) - let cost = this.safeFloat (trade, 'execCost'); + let cost = this.safeNumber (trade, 'execCost'); if (cost !== undefined) { cost = Math.abs (cost) / 100000000; } let fee = undefined; if ('execComm' in trade) { - let feeCost = this.safeFloat (trade, 'execComm'); + let feeCost = this.safeNumber (trade, 'execComm'); feeCost = feeCost / 100000000; const currencyId = this.safeString (trade, 'settlCurrency'); const feeCurrency = this.safeCurrencyCode (currencyId); - const feeRate = this.safeFloat (trade, 'commission'); + const feeRate = this.safeNumber (trade, 'commission'); fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -1262,33 +1259,19 @@ module.exports = class bitmex extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'transactTime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty', 0.0); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (amount - filled, 0.0); - } - } - const average = this.safeFloat (order, 'avgPx'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = average * filled; - } else if (price !== undefined) { - cost = price * filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty', 0.0); + const average = this.safeNumber (order, 'avgPx'); const id = this.safeString (order, 'orderID'); const type = this.safeStringLower (order, 'ordType'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'clOrdID'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const execInst = this.safeString (order, 'execInst'); const postOnly = (execInst === 'ParticipateDoNotInitiate'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1303,14 +1286,14 @@ module.exports = class bitmex extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { @@ -1371,7 +1354,7 @@ module.exports = class bitmex extends Exchange { 'ordType': orderType, }; if ((orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched')) { - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPx or stopPrice parameter for the ' + orderType + ' order type'); } else { @@ -1488,7 +1471,7 @@ module.exports = class bitmex extends Exchange { return this.parseOrders (response, market); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPosition (params); // [ diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitpanda.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitpanda.js index b440aba7d..5f857014b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitpanda.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitpanda.js @@ -328,7 +328,7 @@ module.exports = class bitpanda extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; @@ -401,9 +401,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -450,8 +450,8 @@ module.exports = class bitpanda extends Exchange { const activeFeeTier = this.safeValue (response, 'active_fee_tier', {}); const result = { 'info': response, - 'maker': this.safeFloat (activeFeeTier, 'maker_fee'), - 'taker': this.safeFloat (activeFeeTier, 'taker_fee'), + 'maker': this.safeNumber (activeFeeTier, 'maker_fee'), + 'taker': this.safeNumber (activeFeeTier, 'taker_fee'), 'percentage': true, 'tierBased': true, }; @@ -460,9 +460,9 @@ module.exports = class bitpanda extends Exchange { const makerFees = []; for (let i = 0; i < feeTiers.length; i++) { const tier = feeTiers[i]; - const volume = this.safeFloat (tier, 'volume'); - let taker = this.safeFloat (tier, 'taker_fee'); - let maker = this.safeFloat (tier, 'maker_fee'); + const volume = this.safeNumber (tier, 'volume'); + let taker = this.safeNumber (tier, 'taker_fee'); + let maker = this.safeNumber (tier, 'maker_fee'); taker /= 100; maker /= 100; takerFees.push ([ volume, taker ]); @@ -500,27 +500,27 @@ module.exports = class bitpanda extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last_price'); - const percentage = this.safeFloat (ticker, 'price_change_percentage'); - const change = this.safeFloat (ticker, 'price_change'); + const last = this.safeNumber (ticker, 'last_price'); + const percentage = this.safeNumber (ticker, 'price_change_percentage'); + const change = this.safeNumber (ticker, 'price_change'); let open = undefined; let average = undefined; if ((last !== undefined) && (change !== undefined)) { open = last - change; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'best_bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'best_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'best_ask'), + 'ask': this.safeNumber (ticker, 'best_ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -705,11 +705,11 @@ module.exports = class bitpanda extends Exchange { const volumeField = this.safeString (options, 'volume', 'total_amount'); return [ alignedTimestamp, - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -795,21 +795,21 @@ module.exports = class bitpanda extends Exchange { timestamp = this.parse8601 (this.safeString (trade, 'time')); } const side = this.safeStringLower2 (trade, 'side', 'taker_side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + let cost = this.safeNumber (trade, 'volume'); if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { cost = amount * price; } const marketId = this.safeString (trade, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const feeCost = this.safeFloat (feeInfo, 'fee_amount'); + const feeCost = this.safeNumber (feeInfo, 'fee_amount'); let takerOrMaker = undefined; let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (feeInfo, 'fee_percentage'); + const feeRate = this.safeNumber (feeInfo, 'fee_percentage'); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, @@ -892,11 +892,11 @@ module.exports = class bitpanda extends Exchange { const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -1150,12 +1150,12 @@ module.exports = class bitpanda extends Exchange { // } // const id = this.safeString (transaction, 'transaction_id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const currencyId = this.safeString (transaction, 'currency'); currency = this.safeCurrency (currencyId, currency); const status = 'ok'; // the exchange returns cleared transactions only - const feeCost = this.safeFloat2 (transaction, 'fee_amount', 'fee'); + const feeCost = this.safeNumber2 (transaction, 'fee_amount', 'fee'); let fee = undefined; const addressTo = this.safeString (transaction, 'recipient'); const tagTo = this.safeString (transaction, 'destination_tag'); @@ -1270,72 +1270,34 @@ module.exports = class bitpanda extends Exchange { // ] // } // - const rawTrades = this.safeValue (order, 'trades', []); - order = this.safeValue (order, 'order', order); - const id = this.safeString (order, 'order_id'); - const clientOrderId = this.safeString (order, 'client_id'); - const timestamp = this.parse8601 (this.safeString (order, 'time')); - let status = this.parseOrderStatus (this.safeString (order, 'status')); - const marketId = this.safeString (order, 'instrument_code'); + const rawOrder = this.safeValue (order, 'order', order); + const id = this.safeString (rawOrder, 'order_id'); + const clientOrderId = this.safeString (rawOrder, 'client_id'); + const timestamp = this.parse8601 (this.safeString (rawOrder, 'time')); + const rawStatus = this.parseOrderStatus (this.safeString (rawOrder, 'status')); + const status = this.parseOrderStatus (rawStatus); + const marketId = this.safeString (rawOrder, 'instrument_code'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - if (status === undefined) { - if (remaining > 0) { - status = 'open'; - } else { - status = 'closed'; - } - } - } - } - const side = this.safeStringLower (order, 'side'); - const type = this.safeStringLower (order, 'type'); - const trades = this.parseTrades (rawTrades, market, undefined, undefined); - const fees = []; - const numTrades = trades.length; - let lastTradeTimestamp = undefined; - let tradeCost = undefined; - let tradeAmount = undefined; - if (numTrades > 0) { - lastTradeTimestamp = trades[0]['timestamp']; - tradeCost = 0; - tradeAmount = 0; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - fees.push (trade['fee']); - lastTradeTimestamp = Math.max (lastTradeTimestamp, trade['timestamp']); - tradeCost = this.sum (tradeCost, trade['cost']); - tradeAmount = this.sum (tradeAmount, trade['amount']); - } - } - let average = this.safeFloat (order, 'average_price'); - if (average === undefined) { - if ((tradeCost !== undefined) && (tradeAmount !== undefined) && (tradeAmount !== 0)) { - average = tradeCost / tradeAmount; - } - } - if (cost === undefined) { - if ((average !== undefined) && (filled !== undefined)) { - cost = average * filled; - } - } - const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'trigger_price'); - const postOnly = this.safeValue (order, 'is_post_only'); - const result = { + const price = this.safeNumber (rawOrder, 'price'); + const amount = this.safeNumber (rawOrder, 'amount'); + const filledString = this.safeString (rawOrder, 'filled_amount'); + const filled = this.parseNumber (filledString); + const side = this.safeStringLower (rawOrder, 'side'); + const type = this.safeStringLower (rawOrder, 'type'); + const timeInForce = this.parseTimeInForce (this.safeString (rawOrder, 'time_in_force')); + const stopPrice = this.safeNumber (rawOrder, 'trigger_price'); + const postOnly = this.safeValue (rawOrder, 'is_post_only'); + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'type': type, + }); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -1344,41 +1306,14 @@ module.exports = class bitpanda extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, // 'fee': undefined, 'trades': trades, - }; - const numFees = fees.length; - if (numFees > 0) { - if (numFees === 1) { - result['fee'] = fees[0]; - } else { - const feesByCurrency = this.groupBy (fees, 'currency'); - const feeCurrencies = Object.keys (feesByCurrency); - const numFeesByCurrency = feeCurrencies.length; - if (numFeesByCurrency === 1) { - const feeCurrency = feeCurrencies[0]; - const feeArray = this.safeValue (feesByCurrency, feeCurrency); - let feeCost = 0; - for (let i = 0; i < feeArray.length; i++) { - feeCost = this.sum (feeCost, feeArray[i]['cost']); - } - result['fee'] = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } else { - result['fees'] = fees; - } - } - } else { - result['fee'] = undefined; - } - return result; + }); } parseTimeInForce (timeInForce) { @@ -1412,7 +1347,7 @@ module.exports = class bitpanda extends Exchange { priceIsRequired = true; } if (uppercaseType === 'STOP') { - const triggerPrice = this.safeFloat (params, 'trigger_price'); + const triggerPrice = this.safeNumber (params, 'trigger_price'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a trigger_price param for ' + type + ' orders'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitso.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitso.js index d8bc07145..defcece54 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitso.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitso.js @@ -157,28 +157,28 @@ module.exports = class bitso extends Exchange { const symbol = base + '/' + quote; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), - 'max': this.safeFloat (market, 'maximum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), + 'max': this.safeNumber (market, 'maximum_amount'), }, 'price': { - 'min': this.safeFloat (market, 'minimum_price'), - 'max': this.safeFloat (market, 'maximum_price'), + 'min': this.safeNumber (market, 'minimum_price'), + 'max': this.safeNumber (market, 'maximum_price'), }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), - 'max': this.safeFloat (market, 'maximum_value'), + 'min': this.safeNumber (market, 'minimum_value'), + 'max': this.safeNumber (market, 'maximum_value'), }, }; - const defaultPricePrecision = this.safeFloat (this.options['precision'], quote, this.options['defaultPrecision']); - const pricePrecision = this.safeFloat (market, 'tick_size', defaultPricePrecision); + const defaultPricePrecision = this.safeNumber (this.options['precision'], quote, this.options['defaultPrecision']); + const pricePrecision = this.safeNumber (market, 'tick_size', defaultPricePrecision); const precision = { - 'amount': this.safeFloat (this.options['precision'], base, this.options['defaultPrecision']), + 'amount': this.safeNumber (this.options['precision'], base, this.options['defaultPrecision']), 'price': pricePrecision, }; const fees = this.safeValue (market, 'fees', {}); const flatRate = this.safeValue (fees, 'flat_rate', {}); - const maker = this.safeFloat (flatRate, 'maker'); - const taker = this.safeFloat (flatRate, 'taker'); + const maker = this.safeNumber (flatRate, 'maker'); + const taker = this.safeNumber (flatRate, 'taker'); const feeTiers = this.safeValue (fees, 'structure', []); const fee = { 'taker': parseFloat (this.decimalToPrecision (taker / 100, ROUND, 0.00000001, TICK_SIZE)), @@ -190,9 +190,9 @@ module.exports = class bitso extends Exchange { const makerFees = []; for (let j = 0; j < feeTiers.length; j++) { const tier = feeTiers[j]; - const volume = this.safeFloat (tier, 'volume'); - const takerFee = this.safeFloat (tier, 'taker'); - const makerFee = this.safeFloat (tier, 'maker'); + const volume = this.safeNumber (tier, 'volume'); + const takerFee = this.safeNumber (tier, 'taker'); + const makerFee = this.safeNumber (tier, 'maker'); const takerFeeToPrecision = parseFloat (this.decimalToPrecision (takerFee / 100, ROUND, 0.00000001, TICK_SIZE)); const makerFeeToPrecision = parseFloat (this.decimalToPrecision (makerFee / 100, ROUND, 0.00000001, TICK_SIZE)); takerFees.push ([ volume, takerFeeToPrecision ]); @@ -232,14 +232,13 @@ module.exports = class bitso extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'locked'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -261,22 +260,22 @@ module.exports = class bitso extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'payload'); const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -297,12 +296,12 @@ module.exports = class bitso extends Exchange { const marketId = this.safeString (trade, 'book'); const symbol = this.safeSymbol (marketId, market, '_'); const side = this.safeString2 (trade, 'side', 'maker_side'); - let amount = this.safeFloat2 (trade, 'amount', 'major'); + let amount = this.safeNumber2 (trade, 'amount', 'major'); if (amount !== undefined) { amount = Math.abs (amount); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fees_amount'); + const feeCost = this.safeNumber (trade, 'fees_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fees_currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -311,11 +310,11 @@ module.exports = class bitso extends Exchange { 'currency': feeCurrency, }; } - let cost = this.safeFloat (trade, 'minor'); + let cost = this.safeNumber (trade, 'minor'); if (cost !== undefined) { cost = Math.abs (cost); } - const price = this.safeFloat (trade, 'price'); + const price = this.safeNumber (trade, 'price'); const orderId = this.safeString (trade, 'oid'); const id = this.safeString (trade, 'tid'); return { @@ -416,17 +415,11 @@ module.exports = class bitso extends Exchange { const symbol = this.safeSymbol (marketId, market, '_'); const orderType = this.safeString (order, 'type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'unfilled_amount'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'unfilled_amount'); const clientOrderId = this.safeString (order, 'client_id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -443,12 +436,12 @@ module.exports = class bitso extends Exchange { 'amount': amount, 'cost': undefined, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = 25, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp.js index 4671385bf..0ac6fe9f7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp.js @@ -115,6 +115,16 @@ module.exports = class bitstamp extends Exchange { 'usdc_address/', 'omg_withdrawal/', 'omg_address/', + 'dai_withdrawal/', + 'dai_address/', + 'knc_withdrawal/', + 'knc_address/', + 'mkr_withdrawal/', + 'mkr_address/', + 'zrx_withdrawal/', + 'zrx_address/', + 'gusd_withdrawal/', + 'gusd_address/', 'transfer-to-main/', 'transfer-from-main/', 'withdrawal-requests/', @@ -249,13 +259,15 @@ module.exports = class bitstamp extends Exchange { const symbolId = baseId + '_' + quoteId; const id = this.safeString (market, 'url_symbol'); const precision = { - 'amount': market['base_decimals'], - 'price': market['counter_decimals'], + 'amount': this.safeInteger (market, 'base_decimals'), + 'price': this.safeInteger (market, 'counter_decimals'), }; - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; // let [ cost, currency ] = market['minimum_order'].split (' '); - const active = (market['trading'] === 'Enabled'); + const trading = this.safeString (market, 'trading'); + const active = (trading === 'Enabled'); result.push ({ 'id': id, 'symbol': symbol, @@ -299,7 +311,7 @@ module.exports = class bitstamp extends Exchange { 'type': currencyType, 'name': name, 'active': true, - 'fee': this.safeFloat (description['fees']['funding']['withdraw'], code), + 'fee': this.safeNumber (description['fees']['funding']['withdraw'], code), 'precision': precision, 'limits': { 'amount': { @@ -352,13 +364,16 @@ module.exports = class bitstamp extends Exchange { quote = this.safeCurrencyCode (quote); const description = this.safeString (market, 'description'); const [ baseDescription, quoteDescription ] = description.split (' / '); - const parts = market['minimum_order'].split (' '); + const minimumOrder = this.safeString (market, 'minimum_order'); + const parts = minimumOrder.split (' '); const cost = parts[0]; if (!(base in result)) { - result[base] = this.constructCurrencyObject (baseId, base, baseDescription, market['base_decimals'], undefined, market); + const baseDecimals = this.safeInteger (market, 'base_decimals'); + result[base] = this.constructCurrencyObject (baseId, base, baseDescription, baseDecimals, undefined, market); } if (!(quote in result)) { - result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, market['counter_decimals'], parseFloat (cost), market); + const counterDecimals = this.safeInteger (market, 'counter_decimals'); + result[quote] = this.constructCurrencyObject (quoteId, quote, quoteDescription, counterDecimals, parseFloat (cost), market); } } return result; @@ -400,25 +415,25 @@ module.exports = class bitstamp extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -461,7 +476,7 @@ module.exports = class bitstamp extends Exchange { for (let i = 0; i < ids.length; i++) { const id = ids[i]; if (id.indexOf ('_') < 0) { - const value = this.safeFloat (transaction, id); + const value = this.safeNumber (transaction, id); if ((value !== undefined) && (value !== 0)) { return id; } @@ -543,11 +558,11 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString2 (trade, 'id', 'tid'); let symbol = undefined; let side = undefined; - let price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat (trade, 'amount'); + let price = this.safeNumber (trade, 'price'); + let amount = this.safeNumber (trade, 'amount'); const orderId = this.safeString (trade, 'order_id'); const type = undefined; - let cost = this.safeFloat (trade, 'cost'); + let cost = this.safeNumber (trade, 'cost'); if (market === undefined) { const keys = Object.keys (trade); for (let i = 0; i < keys.length; i++) { @@ -564,12 +579,12 @@ module.exports = class bitstamp extends Exchange { market = this.getMarketFromTrade (trade); } } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let feeCurrency = undefined; if (market !== undefined) { - price = this.safeFloat (trade, market['symbolId'], price); - amount = this.safeFloat (trade, market['baseId'], amount); - cost = this.safeFloat (trade, market['quoteId'], cost); + price = this.safeNumber (trade, market['symbolId'], price); + amount = this.safeNumber (trade, market['baseId'], amount); + cost = this.safeNumber (trade, market['quoteId'], cost); feeCurrency = market['quote']; symbol = market['symbol']; } @@ -638,7 +653,7 @@ module.exports = class bitstamp extends Exchange { parseTradingFee (balances, symbol) { const market = this.market (symbol); - const tradeFee = this.safeFloat (balances, market['id'] + '_fee'); + const tradeFee = this.safeNumber (balances, market['id'] + '_fee'); return { 'symbol': symbol, 'maker': tradeFee, @@ -688,11 +703,11 @@ module.exports = class bitstamp extends Exchange { // return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -750,12 +765,12 @@ module.exports = class bitstamp extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFee (symbol, params = {}) { @@ -802,7 +817,7 @@ module.exports = class bitstamp extends Exchange { if (id.indexOf ('_withdrawal_fee') >= 0) { const currencyId = id.split ('_')[0]; const code = this.safeCurrencyCode (currencyId); - withdraw[code] = this.safeFloat (balance, id); + withdraw[code] = this.safeNumber (balance, id); } } return { @@ -1048,16 +1063,16 @@ module.exports = class bitstamp extends Exchange { const id = this.safeString (transaction, 'id'); const currencyId = this.getCurrencyIdFromTransaction (transaction); const code = this.safeCurrencyCode (currencyId, currency); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let feeCurrency = undefined; let amount = undefined; if ('amount' in transaction) { - amount = this.safeFloat (transaction, 'amount'); + amount = this.safeNumber (transaction, 'amount'); } else if (currency !== undefined) { - amount = this.safeFloat (transaction, currency['id'], amount); + amount = this.safeNumber (transaction, currency['id'], amount); feeCurrency = currency['code']; } else if ((code !== undefined) && (currencyId !== undefined)) { - amount = this.safeFloat (transaction, currencyId, amount); + amount = this.safeNumber (transaction, currencyId, amount); feeCurrency = code; } if (amount !== undefined) { @@ -1182,83 +1197,23 @@ module.exports = class bitstamp extends Exchange { } // there is no timestamp from fetchOrder const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - let lastTradeTimestamp = undefined; - let symbol = undefined; - let marketId = this.safeStringLower (order, 'currency_pair'); - if (marketId !== undefined) { - marketId = marketId.replace ('/', ''); - if (marketId in this.markets_by_id) { - market = this.markets_by_id[marketId]; - symbol = market['symbol']; - } - } - let amount = this.safeFloat (order, 'amount'); - let filled = 0.0; - const trades = []; - const transactions = this.safeValue (order, 'transactions', []); - let feeCost = undefined; - let cost = undefined; - const numTransactions = transactions.length; - if (numTransactions > 0) { - feeCost = 0.0; - for (let i = 0; i < numTransactions; i++) { - const trade = this.parseTrade (this.extend ({ - 'order_id': id, - 'side': side, - }, transactions[i]), market); - filled = this.sum (filled, trade['amount']); - feeCost = this.sum (feeCost, trade['fee']['cost']); - if (cost === undefined) { - cost = 0.0; - } - cost = this.sum (cost, trade['cost']); - trades.push (trade); - } - lastTradeTimestamp = trades[numTransactions - 1]['timestamp']; - } + const marketId = this.safeStringLower (order, 'currency_pair'); + let symbol = this.safeSymbol (marketId, market, '/'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((status === 'closed') && (amount === undefined)) { - amount = filled; + const amount = this.safeNumber (order, 'amount'); + const transactions = this.safeValue (order, 'transactions', []); + const trades = this.parseTrades (transactions, market); + const length = trades.length; + if (length) { + symbol = trades[0]['symbol']; } - let remaining = undefined; - if (amount !== undefined) { - remaining = amount - filled; - } - let price = this.safeFloat (order, 'price'); - if (market === undefined) { - market = this.getMarketFromTrades (trades); - } - let feeCurrency = undefined; - if (market !== undefined) { - if (symbol === undefined) { - symbol = market['symbol']; - } - feeCurrency = market['quote']; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if (price === undefined) { - if (filled > 0) { - price = cost / filled; - } - } - let fee = undefined; - if (feeCost !== undefined) { - if (feeCurrency !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { + const price = this.safeNumber (order, 'price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'status': status, 'symbol': symbol, 'type': undefined, @@ -1267,15 +1222,15 @@ module.exports = class bitstamp extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, - 'filled': filled, - 'remaining': remaining, + 'filled': undefined, + 'remaining': undefined, 'trades': trades, - 'fee': fee, + 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } parseLedgerEntryType (type) { @@ -1355,11 +1310,11 @@ module.exports = class bitstamp extends Exchange { const parsedTransaction = this.parseTransaction (item); let direction = undefined; if ('amount' in item) { - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); direction = amount > 0 ? 'in' : 'out'; } else if (('currency' in parsedTransaction) && parsedTransaction['currency'] !== undefined) { const currencyId = this.currencyId (parsedTransaction['currency']); - const amount = this.safeFloat (item, currencyId); + const amount = this.safeNumber (item, currencyId); direction = amount > 0 ? 'in' : 'out'; } return { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp1.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp1.js index 8d8de5db1..2b6b70a04 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp1.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitstamp1.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -100,25 +101,25 @@ module.exports = class bitstamp1 extends Exchange { await this.loadMarkets (); const ticker = await this.publicGetTicker (params); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, @@ -141,14 +142,11 @@ module.exports = class bitstamp1 extends Exchange { } } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -192,12 +190,12 @@ module.exports = class bitstamp1 extends Exchange { const currency = this.currency (code); const currencyId = currency['id']; const account = this.account (); - account['free'] = this.safeFloat (balance, currencyId + '_available'); - account['used'] = this.safeFloat (balance, currencyId + '_reserved'); - account['total'] = this.safeFloat (balance, currencyId + '_balance'); + account['free'] = this.safeString (balance, currencyId + '_available'); + account['used'] = this.safeString (balance, currencyId + '_reserved'); + account['total'] = this.safeString (balance, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bittrex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bittrex.js index 1e11d600a..fb8f6fb09 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bittrex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bittrex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, DDoSProtection, PermissionDenied, AddressPending, OnMaintenance, BadRequest, InvalidAddress } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -280,7 +281,7 @@ module.exports = class bittrex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeSize'), + 'min': this.safeNumber (market, 'minTradeSize'), 'max': undefined, }, 'price': { @@ -308,11 +309,11 @@ module.exports = class bittrex extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); const balance = indexed[currencyId]; - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -372,7 +373,7 @@ module.exports = class bittrex extends Exchange { const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); const precision = 8; // default precision, todo: fix "magic constants" - const fee = this.safeFloat (currency, 'txFee'); // todo: redesign + const fee = this.safeNumber (currency, 'txFee'); // todo: redesign const isActive = this.safeString (currency, 'status'); result[code] = { 'id': id, @@ -433,17 +434,17 @@ module.exports = class bittrex extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'updatedAt')); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const percentage = this.safeFloat (ticker, 'percentChange'); - const last = this.safeFloat (ticker, 'lastTradeRate'); + const percentage = this.safeNumber (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'lastTradeRate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidRate'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidRate'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'askRate'), + 'ask': this.safeNumber (ticker, 'askRate'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -453,8 +454,8 @@ module.exports = class bittrex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -567,21 +568,18 @@ module.exports = class bittrex extends Exchange { const order = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'marketSymbol'); market = this.safeMarket (marketId, market, '-'); - let cost = undefined; - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'quantity'); - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = undefined; const isTaker = this.safeValue (trade, 'isTaker'); if (isTaker !== undefined) { takerOrMaker = isTaker ? 'taker' : 'maker'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -651,11 +649,11 @@ module.exports = class bittrex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'startsAt')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -762,9 +760,9 @@ module.exports = class bittrex extends Exchange { let cost = undefined; if (isCeilingLimit) { request['limit'] = this.priceToPrecision (symbol, price); - cost = this.safeFloat2 (params, 'ceiling', 'cost', amount); + cost = this.safeNumber2 (params, 'ceiling', 'cost', amount); } else if (isCeilingMarket) { - cost = this.safeFloat2 (params, 'ceiling', 'cost'); + cost = this.safeNumber2 (params, 'ceiling', 'cost'); if (cost === undefined) { if (price === undefined) { cost = amount; @@ -923,7 +921,7 @@ module.exports = class bittrex extends Exchange { // } // const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const address = this.safeString (transaction, 'cryptoAddress'); const txid = this.safeString (transaction, 'txId'); const updated = this.parse8601 (this.safeString (transaction, 'updatedAt')); @@ -959,7 +957,7 @@ module.exports = class bittrex extends Exchange { status = 'ok'; } } - let feeCost = this.safeFloat (transaction, 'txCost'); + let feeCost = this.safeNumber (transaction, 'txCost'); if (feeCost === undefined) { if (type === 'deposit') { // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge- @@ -1016,15 +1014,9 @@ module.exports = class bittrex extends Exchange { // } // const marketSymbol = this.safeString (order, 'marketSymbol'); - let symbol = undefined; - let feeCurrency = undefined; - if (marketSymbol !== undefined) { - const [ baseId, quoteId ] = marketSymbol.split ('-'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - symbol = base + '/' + quote; - feeCurrency = quote; - } + market = this.safeMarket (marketSymbol, market, '-'); + const symbol = market['symbol']; + const feeCurrency = market['quote']; const direction = this.safeStringLower (order, 'direction'); const createdAt = this.safeString (order, 'createdAt'); const updatedAt = this.safeString (order, 'updatedAt'); @@ -1037,32 +1029,15 @@ module.exports = class bittrex extends Exchange { } const timestamp = this.parse8601 (createdAt); const type = this.safeStringLower (order, 'type'); - const quantity = this.safeFloat (order, 'quantity'); - const limit = this.safeFloat (order, 'limit'); - const fillQuantity = this.safeFloat (order, 'fillQuantity'); - const commission = this.safeFloat (order, 'commission'); - const proceeds = this.safeFloat (order, 'proceeds'); - let average = undefined; - let remaining = undefined; - if (fillQuantity !== undefined) { - if (proceeds !== undefined) { - if (fillQuantity > 0) { - average = proceeds / fillQuantity; - } else if (proceeds === 0) { - average = 0; - } - } - if (quantity !== undefined) { - remaining = quantity - fillQuantity; - } - } - let status = this.safeStringLower (order, 'status'); - if ((status === 'closed') && (remaining !== undefined) && (remaining > 0)) { - status = 'canceled'; - } + const quantity = this.safeNumber (order, 'quantity'); + const limit = this.safeNumber (order, 'limit'); + const fillQuantity = this.safeNumber (order, 'fillQuantity'); + const commission = this.safeNumber (order, 'commission'); + const proceeds = this.safeNumber (order, 'proceeds'); + const status = this.safeStringLower (order, 'status'); const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'timestamp': timestamp, @@ -1076,10 +1051,10 @@ module.exports = class bittrex extends Exchange { 'price': limit, 'stopPrice': undefined, 'cost': proceeds, - 'average': average, + 'average': undefined, 'amount': quantity, 'filled': fillQuantity, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': { 'cost': commission, @@ -1087,7 +1062,7 @@ module.exports = class bittrex extends Exchange { }, 'info': order, 'trades': undefined, - }; + }); } parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { @@ -1136,9 +1111,9 @@ module.exports = class bittrex extends Exchange { 'side': this.safeString (order, 'side'), 'order': this.safeString (order, 'id'), 'type': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'average'), - 'amount': this.safeFloat (order, 'filled'), - 'cost': this.safeFloat (order, 'cost'), + 'price': this.safeNumber (order, 'average'), + 'amount': this.safeNumber (order, 'filled'), + 'cost': this.safeNumber (order, 'cost'), 'symbol': this.safeString (order, 'symbol'), 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitvavo.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitvavo.js index e6633b568..ef66620ca 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitvavo.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitvavo.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors'); const { SIGNIFICANT_DIGITS, DECIMAL_PLACES, TRUNCATE, ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -306,7 +307,7 @@ module.exports = class bitvavo extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minOrderInBaseAsset'), + 'min': this.safeNumber (market, 'minOrderInBaseAsset'), 'max': undefined, }, 'price': { @@ -314,7 +315,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderInQuoteAsset'), + 'min': this.safeNumber (market, 'minOrderInQuoteAsset'), 'max': undefined, }, }, @@ -377,7 +378,7 @@ module.exports = class bitvavo extends Exchange { 'code': code, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -393,7 +394,7 @@ module.exports = class bitvavo extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMinAmount'), + 'min': this.safeNumber (currency, 'withdrawalMinAmount'), 'max': undefined, }, }, @@ -450,14 +451,14 @@ module.exports = class bitvavo extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.safeInteger (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); + const last = this.safeNumber (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); const vwap = this.vwap (baseVolume, quoteVolume); let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'open'); + const open = this.safeNumber (ticker, 'open'); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -469,12 +470,12 @@ module.exports = class bitvavo extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': vwap, 'open': open, 'close': last, @@ -490,14 +491,6 @@ module.exports = class bitvavo extends Exchange { return result; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24h (params); @@ -611,12 +604,11 @@ module.exports = class bitvavo extends Exchange { // feeCurrency: 'EUR' // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'side'); const id = this.safeString2 (trade, 'id', 'fillId'); @@ -627,7 +619,7 @@ module.exports = class bitvavo extends Exchange { if (taker !== undefined) { takerOrMaker = taker ? 'taker' : 'maker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); @@ -698,11 +690,11 @@ module.exports = class bitvavo extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -750,13 +742,12 @@ module.exports = class bitvavo extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'inOrder'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'inOrder'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchDepositAddress (code, params = {}) { @@ -806,7 +797,7 @@ module.exports = class bitvavo extends Exchange { if (price !== undefined) { cost = amount * price; } else { - cost = this.safeFloat2 (params, 'cost', 'amountQuote'); + cost = this.safeNumber2 (params, 'cost', 'amountQuote'); } if (cost !== undefined) { const precision = market['precision']['price']; @@ -819,7 +810,7 @@ module.exports = class bitvavo extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['amount'] = this.amountToPrecision (symbol, amount); } else if (isStopMarket || isStopLimit) { - let stopPrice = this.safeFloat2 (params, 'stopPrice', 'triggerAmount'); + let stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerAmount'); if (stopPrice === undefined) { if (isStopLimit) { throw new ArgumentsRequired (this.id + ' createOrder requires a stopPrice parameter for a ' + type + ' order'); @@ -881,7 +872,7 @@ module.exports = class bitvavo extends Exchange { await this.loadMarkets (); const market = this.market (symbol); let request = {}; - const amountRemaining = this.safeFloat (params, 'amountRemaining'); + const amountRemaining = this.safeNumber (params, 'amountRemaining'); params = this.omit (params, 'amountRemaining'); if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); @@ -946,7 +937,6 @@ module.exports = class bitvavo extends Exchange { throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument'); } await this.loadMarkets (); - await this.loadMarkets (); const market = this.market (symbol); const request = { 'orderId': id, @@ -1172,26 +1162,13 @@ module.exports = class bitvavo extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let remaining = this.safeFloat (order, 'amountRemaining'); - let filled = this.safeFloat (order, 'filledAmount'); - const remainingCost = this.safeFloat (order, 'remainingCost'); - if ((remainingCost !== undefined) && (remainingCost === 0.0)) { - remaining = 0; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - const cost = this.safeFloat (order, 'filledAmountQuote'); - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amountRemaining'); + const filled = this.safeNumber (order, 'filledAmount'); + const cost = this.safeNumber (order, 'filledAmountQuote'); let fee = undefined; - const feeCost = this.safeFloat (order, 'feePaid'); + const feeCost = this.safeNumber (order, 'feePaid'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1200,32 +1177,24 @@ module.exports = class bitvavo extends Exchange { 'currency': feeCurrencyCode, }; } - let lastTradeTimestamp = undefined; - const rawTrades = this.safeValue (order, 'fills'); - let trades = undefined; - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'symbol': symbol, - 'order': id, - 'side': side, - }); - const numTrades = trades.length; - if (numTrades > 0) { - const lastTrade = this.safeValue (trades, numTrades - 1); - lastTradeTimestamp = lastTrade['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'fills', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'symbol': symbol, + 'order': id, + 'side': side, + 'type': type, + }); const timeInForce = this.safeString (order, 'timeInForce'); const postOnly = this.safeValue (order, 'postOnly'); // https://github.com/ccxt/ccxt/issues/8489 - const stopPrice = this.safeFloat (order, 'triggerPrice'); - return { + const stopPrice = this.safeNumber (order, 'triggerPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': timeInForce, @@ -1235,13 +1204,13 @@ module.exports = class bitvavo extends Exchange { 'stopPrice': stopPrice, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1436,11 +1405,11 @@ module.exports = class bitvavo extends Exchange { const currencyId = this.safeString (transaction, 'symbol'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitz.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitz.js index 816bb15a4..d78900841 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitz.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bitz.js @@ -59,7 +59,7 @@ module.exports = class bitz extends Exchange { 'assets': 'https://{hostname}', }, 'www': 'https://www.bitz.com', - 'doc': 'https://apidoc.bitz.com/en/', + 'doc': 'https://apidocv2.bitz.plus/en/', 'fees': 'https://www.bitz.com/fee?type=1', 'referral': 'https://u.bitz.com/register?invite_code=1429193', }, @@ -76,6 +76,11 @@ module.exports = class bitz extends Exchange { 'currencyRate', 'currencyCoinRate', 'coinRate', + 'getContractCoin', + 'getContractKline', + 'getContractOrderBook', + 'getContractTradesHistory', + 'getContractTickers', ], }, 'trade': { @@ -88,6 +93,10 @@ module.exports = class bitz extends Exchange { 'getUserNowEntrustSheet', // open orders 'getEntrustSheetInfo', // order 'depositOrWithdraw', // transactions + 'getCoinAddress', + 'getCoinAddressList', + 'marketTrade', + 'addEntrustSheetBatch', ], }, 'assets': { @@ -95,6 +104,20 @@ module.exports = class bitz extends Exchange { 'getUserAssets', ], }, + 'contract': { + 'post': [ + 'addContractTrade', + 'cancelContractTrade', + 'getContractActivePositions', + 'getContractAccountInfo', + 'getContractMyPositions', + 'getContractOrderResult', + 'getContractTradeResult', + 'getContractOrder', + 'getContractMyHistoryTrade', + 'getContractMyTrades', + ], + }, }, 'fees': { 'trading': { @@ -281,8 +304,8 @@ module.exports = class bitz extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTrade'), - 'max': this.safeFloat (market, 'maxTrade'), + 'min': this.safeNumber (market, 'minTrade'), + 'max': this.safeNumber (market, 'maxTrade'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -331,12 +354,12 @@ module.exports = class bitz extends Exchange { const currencyId = this.safeString (balance, 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'lock'); - account['total'] = this.safeFloat (balance, 'num'); - account['free'] = this.safeFloat (balance, 'over'); + account['used'] = this.safeString (balance, 'lock'); + account['total'] = this.safeString (balance, 'num'); + account['free'] = this.safeString (balance, 'over'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTicker (ticker, market = undefined) { @@ -366,8 +389,8 @@ module.exports = class bitz extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'now'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'now'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -378,22 +401,22 @@ module.exports = class bitz extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': change, - 'percentage': this.safeFloat (ticker, 'priceChange24h'), + 'percentage': this.safeNumber (ticker, 'priceChange24h'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -583,8 +606,8 @@ module.exports = class bitz extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const price = this.safeFloat (trade, 'p'); - const amount = this.safeFloat (trade, 'n'); + const price = this.safeNumber (trade, 'p'); + const amount = this.safeNumber (trade, 'n'); let cost = undefined; if (price !== undefined) { if (amount !== undefined) { @@ -652,11 +675,11 @@ module.exports = class bitz extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -754,22 +777,17 @@ module.exports = class bitz extends Exchange { if (side !== undefined) { side = (side === 'sale') ? 'sell' : 'buy'; } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'number'); - const remaining = this.safeFloat (order, 'numberOver'); - const filled = this.safeFloat (order, 'numberDeal'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'number'); + const remaining = this.safeNumber (order, 'numberOver'); + const filled = this.safeNumber (order, 'numberDeal'); let timestamp = this.safeInteger (order, 'timestamp'); if (timestamp === undefined) { timestamp = this.safeTimestamp (order, 'created'); } - let cost = this.safeFloat (order, 'orderTotalPrice'); - if (price !== undefined) { - if (filled !== undefined) { - cost = filled * price; - } - } + const cost = this.safeNumber (order, 'orderTotalPrice'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -791,7 +809,7 @@ module.exports = class bitz extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1118,7 +1136,7 @@ module.exports = class bitz extends Exchange { const type = this.safeStringLower (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'network_fee'); + const feeCost = this.safeNumber (transaction, 'network_fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1133,7 +1151,7 @@ module.exports = class bitz extends Exchange { 'address': this.safeString (transaction, 'wallet'), 'tag': this.safeString (transaction, 'memo'), 'type': type, - 'amount': this.safeFloat (transaction, 'number'), + 'amount': this.safeNumber (transaction, 'number'), 'currency': code, 'status': status, 'updated': timestamp, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bl3p.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bl3p.js index bb84442ec..832b5dc6f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bl3p.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bl3p.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -81,17 +82,19 @@ module.exports = class bl3p extends Exchange { const available = this.safeValue (wallet, 'available', {}); const balance = this.safeValue (wallet, 'balance', {}); const account = this.account (); - account['free'] = this.safeFloat (available, 'value'); - account['total'] = this.safeFloat (balance, 'value'); + account['free'] = this.safeString (available, 'value'); + account['total'] = this.safeString (balance, 'value'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { + const price = this.safeNumber (bidask, priceKey); + const size = this.safeNumber (bidask, amountKey); return [ - bidask[priceKey] / 100000.0, - bidask[amountKey] / 100000000.0, + price / 100000.0, + size / 100000000.0, ]; } @@ -111,16 +114,16 @@ module.exports = class bl3p extends Exchange { }; const ticker = await this.publicGetMarketTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -130,7 +133,7 @@ module.exports = class bl3p extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker['volume'], '24h'), + 'baseVolume': this.safeNumber (ticker['volume'], '24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -139,20 +142,13 @@ module.exports = class bl3p extends Exchange { parseTrade (trade, market = undefined) { const id = this.safeString (trade, 'trade_id'); const timestamp = this.safeInteger (trade, 'date'); - let price = this.safeFloat (trade, 'price_int'); - if (price !== undefined) { - price /= 100000.0; - } - let amount = this.safeFloat (trade, 'amount_int'); - if (amount !== undefined) { - amount /= 100000000.0; - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + let priceString = this.safeString (trade, 'price_int'); + priceString = Precise.stringDiv (priceString, '100000'); + let amountString = this.safeString (trade, 'amount_int'); + amountString = Precise.stringDiv (amountString, '100000000'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bleutrade.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bleutrade.js index 67262da33..01e7d30ce 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bleutrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bleutrade.js @@ -163,8 +163,8 @@ module.exports = class bleutrade extends Exchange { 'code': code, 'name': this.safeString (item, 'AssetLong'), 'active': this.safeValue (item, 'IsActive') && !this.safeValue (item, 'MaintenanceMode'), - 'fee': this.safeFloat (item, 'WithdrawTxFee'), - 'precision': this.safeFloat (item, 'DecimalPlaces'), + 'fee': this.safeNumber (item, 'WithdrawTxFee'), + 'precision': this.safeNumber (item, 'DecimalPlaces'), 'info': item, 'limits': this.limits, }; @@ -216,7 +216,7 @@ module.exports = class bleutrade extends Exchange { 'taker': this.fees['trading']['taker'], 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinTradeSize'), + 'min': this.safeNumber (market, 'MinTradeSize'), 'max': undefined, }, 'price': { @@ -292,8 +292,8 @@ module.exports = class bleutrade extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'TimeStamp')); const marketId = this.safeString (ticker, 'MarketName'); const symbol = this.safeSymbol (marketId, market, '_'); - const previous = this.safeFloat (ticker, 'PrevDay'); - const last = this.safeFloat (ticker, 'Last'); + const previous = this.safeNumber (ticker, 'PrevDay'); + const last = this.safeNumber (ticker, 'Last'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -308,11 +308,11 @@ module.exports = class bleutrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'High'), - 'low': this.safeFloat (ticker, 'Low'), - 'bid': this.safeFloat (ticker, 'Bid'), + 'high': this.safeNumber (ticker, 'High'), + 'low': this.safeNumber (ticker, 'Low'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': previous, @@ -322,8 +322,8 @@ module.exports = class bleutrade extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume'), - 'quoteVolume': this.safeFloat (ticker, 'BaseVolume'), + 'baseVolume': this.safeNumber (ticker, 'Volume'), + 'quoteVolume': this.safeNumber (ticker, 'BaseVolume'), 'info': ticker, }; } @@ -331,11 +331,11 @@ module.exports = class bleutrade extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (ohlcv['TimeStamp'] + '+00:00'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } @@ -411,11 +411,11 @@ module.exports = class bleutrade extends Exchange { const currencyId = this.safeString (item, 'Asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (item, 'Available'); - account['total'] = this.safeFloat (item, 'Balance'); + account['free'] = this.safeString (item, 'Available'); + account['total'] = this.safeString (item, 'Balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -558,7 +558,7 @@ module.exports = class bleutrade extends Exchange { // } const timestamp = this.parse8601 (this.safeString (item, 'TimeStamp')); - let amount = this.safeFloat (item, 'Amount'); + let amount = this.safeNumber (item, 'Amount'); let direction = undefined; if (amount !== undefined) { direction = 'in'; @@ -632,27 +632,12 @@ module.exports = class bleutrade extends Exchange { if ('Created' in order) { timestamp = this.parse8601 (order['Created'] + '+00:00'); } - let price = this.safeFloat (order, 'Price'); - let cost = undefined; - const amount = this.safeFloat (order, 'Quantity'); - const remaining = this.safeFloat (order, 'QuantityRemaining'); - let filled = undefined; - if (amount !== undefined && remaining !== undefined) { - filled = amount - remaining; - } - if (!cost) { - if (price && filled) { - cost = price * filled; - } - } - if (!price) { - if (cost && filled) { - price = cost / filled; - } - } - const average = this.safeFloat (order, 'PricePerUnit'); + const price = this.safeNumber (order, 'Price'); + const amount = this.safeNumber (order, 'Quantity'); + const remaining = this.safeNumber (order, 'QuantityRemaining'); + const average = this.safeNumber (order, 'PricePerUnit'); const id = this.safeString (order, 'OrderID'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -666,15 +651,15 @@ module.exports = class bleutrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -711,7 +696,7 @@ module.exports = class bleutrade extends Exchange { // Symbol: 'BTC' } // const id = this.safeString (transaction, 'ID'); - let amount = this.safeFloat (transaction, 'Amount'); + let amount = this.safeNumber (transaction, 'Amount'); let type = 'deposit'; if (amount < 0) { amount = Math.abs (amount); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/braziliex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/braziliex.js index 0c54e4840..31a519468 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/braziliex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/braziliex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -184,11 +185,11 @@ module.exports = class braziliex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': this.safeFloat (currency, 'txWithdrawalFee'), + 'fee': this.safeNumber (currency, 'txWithdrawalFee'), }, 'deposit': { 'active': canDeposit, - 'fee': this.safeFloat (currency, 'txDepositFee'), + 'fee': this.safeNumber (currency, 'txDepositFee'), }, }, 'limits': { @@ -205,11 +206,11 @@ module.exports = class braziliex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'MinWithdrawal'), + 'min': this.safeNumber (currency, 'MinWithdrawal'), 'max': Math.pow (10, precision), }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, }, @@ -257,9 +258,9 @@ module.exports = class braziliex extends Exchange { const quoteIsFiat = this.safeInteger (quoteCurrency, 'is_fiat', 0); let minCost = undefined; if (quoteIsFiat) { - minCost = this.safeFloat (baseCurrency, 'minAmountTradeFIAT'); + minCost = this.safeNumber (baseCurrency, 'minAmountTradeFIAT'); } else { - minCost = this.safeFloat (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); + minCost = this.safeNumber (baseCurrency, 'minAmountTrade' + uppercaseQuoteId); } const isActive = this.safeInteger (market, 'active'); const active = (isActive === 1); @@ -302,27 +303,27 @@ module.exports = class braziliex extends Exchange { symbol = market['symbol']; } const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highestBid24'), - 'low': this.safeFloat (ticker, 'lowestAsk24'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'highestBid24'), + 'low': this.safeNumber (ticker, 'lowestAsk24'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'percentChange'), + 'change': this.safeNumber (ticker, 'percentChange'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume24'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume24'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24'), 'info': ticker, }; } @@ -362,13 +363,18 @@ module.exports = class braziliex extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString2 (trade, 'date_exec', 'date')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } - const cost = this.safeFloat (trade, 'total'); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_number'); const type = 'limit'; const side = this.safeString (trade, 'type'); @@ -410,11 +416,11 @@ module.exports = class braziliex extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -436,21 +442,16 @@ module.exports = class braziliex extends Exchange { if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'date')); } - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'total', 0.0); - const amount = this.safeFloat (order, 'amount'); - const filledPercentage = this.safeFloat (order, 'progress'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'total'); + const amount = this.safeNumber (order, 'amount'); + const filledPercentage = this.safeNumber (order, 'progress'); const filled = amount * filledPercentage; - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); - let info = order; - if ('info' in info) { - info = order['info']; - } const id = this.safeString (order, 'order_number'); const fee = this.safeValue (order, 'fee'); // propagated from createOrder const status = (filledPercentage === 1.0) ? 'closed' : 'open'; const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -467,12 +468,12 @@ module.exports = class braziliex extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, - 'info': info, + 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -524,7 +525,7 @@ module.exports = class braziliex extends Exchange { 'price': this.safeString (priceParts, 1), 'total': this.safeString (totalParts, 1), 'fee': { - 'cost': this.safeFloat (feeParts, 1), + 'cost': this.safeNumber (feeParts, 1), 'currency': this.safeString (feeParts, 2), }, 'progress': '0.0', diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcalpha.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcalpha.js index 820234604..f7a890dfb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcalpha.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcalpha.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, DDoSProtection, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -145,8 +146,8 @@ module.exports = class btcalpha extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_order_size'), - 'max': this.safeFloat (market, 'maximum_order_size'), + 'min': this.safeNumber (market, 'minimum_order_size'), + 'max': this.safeNumber (market, 'maximum_order_size'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -198,14 +199,11 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'id', 'tid'); const side = this.safeString2 (trade, 'my_side', 'side'); const orderId = this.safeString (trade, 'o_id'); @@ -254,11 +252,11 @@ module.exports = class btcalpha extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -295,11 +293,11 @@ module.exports = class btcalpha extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'reserve'); - account['total'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserve'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -320,8 +318,8 @@ module.exports = class btcalpha extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (order, 'date'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString2 (order, 'oid', 'id'); let trades = this.safeValue (order, 'trades', []); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcbox.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcbox.js index 1a5f82456..48a455625 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcbox.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcbox.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -88,12 +89,12 @@ module.exports = class btcbox extends Exchange { if (free in response) { const account = this.account (); const used = currencyId + '_lock'; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -114,16 +115,16 @@ module.exports = class btcbox extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -133,8 +134,8 @@ module.exports = class btcbox extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -158,14 +159,11 @@ module.exports = class btcbox extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeString (trade, 'type'); return { @@ -265,15 +263,15 @@ module.exports = class btcbox extends Exchange { if (datetimeString !== undefined) { timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time } - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let cost = undefined; if (price !== undefined) { if (filled !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcmarkets.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcmarkets.js index 2340d1960..44cdd0f78 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcmarkets.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcmarkets.js @@ -246,11 +246,11 @@ module.exports = class btcmarkets extends Exchange { const tagTo = tag; const addressFrom = undefined; const tagFrom = undefined; - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const currencyId = this.safeString (transaction, 'assetName'); const code = this.safeCurrencyCode (currencyId); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (fee) { amount -= fee; } @@ -303,10 +303,10 @@ module.exports = class btcmarkets extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const fees = this.safeValue (this.safeValue (this.options, 'fees', {}), quote, this.fees); - const pricePrecision = this.safeFloat (market, 'priceDecimals'); - const amountPrecision = this.safeFloat (market, 'amountDecimals'); - const minAmount = this.safeFloat (market, 'minOrderAmount'); - const maxAmount = this.safeFloat (market, 'maxOrderAmount'); + const pricePrecision = this.safeNumber (market, 'priceDecimals'); + const amountPrecision = this.safeNumber (market, 'amountDecimals'); + const minAmount = this.safeNumber (market, 'minOrderAmount'); + const maxAmount = this.safeNumber (market, 'maxOrderAmount'); let minPrice = undefined; if (quote === 'AUD') { minPrice = Math.pow (10, -pricePrecision); @@ -365,14 +365,12 @@ module.exports = class btcmarkets extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetName'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance, 'balance'); - const used = this.safeFloat (balance, 'locked'); const account = this.account (); - account['used'] = used; - account['total'] = total; + account['used'] = this.safeString (balance, 'locked'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -388,11 +386,11 @@ module.exports = class btcmarkets extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 0)), - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 2), // high - this.safeFloat (ohlcv, 3), // low - this.safeFloat (ohlcv, 4), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 2), // high + this.safeNumber (ohlcv, 3), // low + this.safeNumber (ohlcv, 4), // close + this.safeNumber (ohlcv, 5), // volume ]; } @@ -488,21 +486,21 @@ module.exports = class btcmarkets extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'lastPrice'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); - const quoteVolume = this.safeFloat (ticker, 'volumeQte24h'); + const last = this.safeNumber (ticker, 'lastPrice'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); + const quoteVolume = this.safeNumber (ticker, 'volumeQte24h'); const vwap = this.vwap (baseVolume, quoteVolume); - const change = this.safeFloat (ticker, 'price24h'); - const percentage = this.safeFloat (ticker, 'pricePct24h'); + const change = this.safeNumber (ticker, 'price24h'); + const percentage = this.safeNumber (ticker, 'pricePct24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bestBid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'bestAsk'), + 'ask': this.safeNumber (ticker, 'bestAsk'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -613,8 +611,8 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -623,7 +621,7 @@ module.exports = class btcmarkets extends Exchange { } const orderId = this.safeString (trade, 'orderId'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -714,7 +712,7 @@ module.exports = class btcmarkets extends Exchange { } } if (triggerPriceIsRequired) { - const triggerPrice = this.safeFloat (params, 'triggerPrice'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); params = this.omit (params, 'triggerPrice'); if (triggerPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a triggerPrice parameter for a ' + type + 'order'); @@ -847,9 +845,9 @@ module.exports = class btcmarkets extends Exchange { side = 'sell'; } const type = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'openAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'openAmount'); let filled = undefined; if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); @@ -864,7 +862,7 @@ module.exports = class btcmarkets extends Exchange { const id = this.safeString (order, 'orderId'); const clientOrderId = this.safeString (order, 'clientOrderId'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btctradeua.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btctradeua.js index 011bc33b6..32527f881 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btctradeua.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btctradeua.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -106,10 +107,10 @@ module.exports = class btctradeua extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -249,14 +250,11 @@ module.exports = class btctradeua extends Exchange { const id = this.safeString (trade, 'id'); const type = 'limit'; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amnt_trade'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amnt_trade'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -337,11 +335,11 @@ module.exports = class btctradeua extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeString (order, 'type'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'amount': this.safeFloat (order, 'amnt_trade'), + 'amount': this.safeNumber (order, 'amnt_trade'), 'filled': 0, - 'remaining': this.safeFloat (order, 'amnt_trade'), + 'remaining': this.safeNumber (order, 'amnt_trade'), 'trades': undefined, 'info': order, 'cost': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcturk.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcturk.js index 32ea74550..2ef97bc99 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcturk.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/btcturk.js @@ -125,13 +125,13 @@ module.exports = class btcturk extends Exchange { const used = currency['id'] + '_reserved'; if (free in response) { const account = this.account (); - account['free'] = this.safeFloat (response, free); - account['total'] = this.safeFloat (response, total); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['total'] = this.safeString (response, total); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -151,26 +151,26 @@ module.exports = class btcturk extends Exchange { symbol = market['symbol']; } const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'average'), - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'average': this.safeNumber (ticker, 'average'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -204,8 +204,8 @@ module.exports = class btcturk extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -247,11 +247,11 @@ module.exports = class btcturk extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.parse8601 (this.safeString (ohlcv, 'Time')), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/buda.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/buda.js index e78c228ea..ac71ec42b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/buda.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/buda.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -220,7 +221,7 @@ module.exports = class buda extends Exchange { } const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); - const precision = this.safeFloat (currency, 'input_decimals'); + const precision = this.safeNumber (currency, 'input_decimals'); const minimum = Math.pow (10, -precision); result[code] = { 'id': id, @@ -381,24 +382,25 @@ module.exports = class buda extends Exchange { let timestamp = undefined; let side = undefined; const type = undefined; - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; const order = undefined; const fee = undefined; let symbol = undefined; - let cost = undefined; if (market) { symbol = market['symbol']; } if (Array.isArray (trade)) { - timestamp = parseInt (trade[0]); - price = parseFloat (trade[1]); - amount = parseFloat (trade[2]); - cost = price * amount; - side = trade[3]; - id = trade[4].toString (); + timestamp = this.safeInteger (trade, 0); + priceString = this.safeString (trade, 1); + amountString = this.safeString (trade, 2); + side = this.safeString (trade, 3); + id = this.safeString (trade, 4); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': order, @@ -453,11 +455,11 @@ module.exports = class buda extends Exchange { const currencyId = this.safeString (balance, 'id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = parseFloat (balance['available_amount'][0]); - account['total'] = parseFloat (balance['amount'][0]); + account['free'] = this.safeString (balance['available_amount'], 0); + account['total'] = this.safeString (balance['amount'], 0); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -565,15 +567,15 @@ module.exports = class buda extends Exchange { const side = this.safeStringLower (order, 'type'); const status = this.parseOrderStatus (this.safeString (order, 'state')); const originalAmount = this.safeValue (order, 'original_amount', []); - const amount = this.safeFloat (originalAmount, 0); + const amount = this.safeNumber (originalAmount, 0); const remainingAmount = this.safeValue (order, 'amount', []); - const remaining = this.safeFloat (remainingAmount, 0); + const remaining = this.safeNumber (remainingAmount, 0); const tradedAmount = this.safeValue (order, 'traded_amount', []); - const filled = this.safeFloat (tradedAmount, 0); + const filled = this.safeNumber (tradedAmount, 0); const totalExchanged = this.safeValue (order, 'totalExchanged', []); - const cost = this.safeFloat (totalExchanged, 0); + const cost = this.safeNumber (totalExchanged, 0); const limitPrice = this.safeValue (order, 'limit', []); - let price = this.safeFloat (limitPrice, 0); + let price = this.safeNumber (limitPrice, 0); if (price === undefined) { if (limitPrice !== undefined) { price = limitPrice; @@ -584,7 +586,7 @@ module.exports = class buda extends Exchange { average = this.priceToPrecision (symbol, cost / filled); } const paidFee = this.safeValue (order, 'paid_fee', []); - const feeCost = this.safeFloat (paidFee, 0); + const feeCost = this.safeNumber (paidFee, 0); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (paidFee, 1); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bw.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bw.js index 388946b39..4fb3b4192 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bw.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bw.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { RateLimitExceeded, BadSymbol, OrderNotFound, ExchangeError, AuthenticationError, ArgumentsRequired, ExchangeNotAvailable } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -185,7 +186,7 @@ module.exports = class bw extends Exchange { const symbol = base + '/' + quote; const state = this.safeInteger (market, 'state'); const active = (state === 1); - const fee = this.safeFloat (market, 'defaultFee'); + const fee = this.safeNumber (market, 'defaultFee'); result.push ({ 'id': id, 'active': active, @@ -206,7 +207,7 @@ module.exports = class bw extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -292,11 +293,11 @@ module.exports = class bw extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'drawFee'), + 'fee': this.safeNumber (currency, 'drawFee'), 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'limitAmount', 0), + 'min': this.safeNumber (currency, 'limitAmount', 0), 'max': undefined, }, 'price': { @@ -309,7 +310,7 @@ module.exports = class bw extends Exchange { }, 'withdraw': { 'min': undefined, - 'max': this.safeFloat (currency, 'onceDrawLimit'), + 'max': this.safeNumber (currency, 'onceDrawLimit'), }, }, }; @@ -346,9 +347,9 @@ module.exports = class bw extends Exchange { 'high': parseFloat (this.safeValue (ticker, 2)), 'low': parseFloat (this.safeValue (ticker, 3)), 'bid': parseFloat (this.safeValue (ticker, 7)), - 'bidVolume': this.safeFloat (bid, 'quantity'), + 'bidVolume': this.safeNumber (bid, 'quantity'), 'ask': parseFloat (this.safeValue (ticker, 8)), - 'askVolume': this.safeFloat (ask, 'quantity'), + 'askVolume': this.safeNumber (ask, 'quantity'), 'vwap': undefined, 'open': undefined, 'close': close, @@ -477,8 +478,11 @@ module.exports = class bw extends Exchange { // ... // const timestamp = this.safeTimestamp (trade, 2); - const price = this.safeFloat (trade, 5); - const amount = this.safeFloat (trade, 6); + const priceString = this.safeString (trade, 5); + const amountString = this.safeString (trade, 6); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 1); let symbol = undefined; if (marketId !== undefined) { @@ -495,12 +499,6 @@ module.exports = class bw extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const sideString = this.safeString (trade, 4); const side = (sideString === 'ask') ? 'sell' : 'buy'; return { @@ -514,7 +512,7 @@ module.exports = class bw extends Exchange { 'takerOrMaker': undefined, 'price': price, 'amount': amount, - 'cost': parseFloat (cost), + 'cost': cost, 'fee': undefined, 'info': trade, }; @@ -571,11 +569,11 @@ module.exports = class bw extends Exchange { // return [ this.safeTimestamp (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), - this.safeFloat (ohlcv, 6), - this.safeFloat (ohlcv, 7), - this.safeFloat (ohlcv, 8), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + this.safeNumber (ohlcv, 6), + this.safeNumber (ohlcv, 7), + this.safeNumber (ohlcv, 8), ]; } @@ -633,11 +631,11 @@ module.exports = class bw extends Exchange { const currencyId = this.safeString (balance, 'currencyTypeId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'amount'); - account['used'] = this.safeFloat (balance, 'freeze'); + account['free'] = this.safeString (balance, 'amount'); + account['used'] = this.safeString (balance, 'freeze'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -733,25 +731,13 @@ module.exports = class bw extends Exchange { } else if (side === '1') { side = 'buy'; } - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'completeAmount'); - let remaining = this.safeFloat2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available - let cost = this.safeFloat (order, 'totalMoney'); - if (filled !== undefined) { - if (amount !== undefined) { - if (remaining === undefined) { - remaining = amount - filled; - } - } - if (cost === undefined) { - if (price !== undefined) { - cost = filled * cost; - } - } - } + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'completeAmount'); + const remaining = this.safeNumber2 (order, 'availabelAmount', 'availableAmount'); // typo in the docs or in the API, availabel vs available + const cost = this.safeNumber (order, 'totalMoney'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'entrustId'), 'clientOrderId': undefined, @@ -773,7 +759,7 @@ module.exports = class bw extends Exchange { 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1069,12 +1055,12 @@ module.exports = class bw extends Exchange { code = currency['code']; } const type = ('depositId' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat2 (transaction, 'actuallyAmount', 'amount'); + const amount = this.safeNumber2 (transaction, 'actuallyAmount', 'amount'); const status = this.parseTransactionStatus (this.safeString2 (transaction, 'verifyStatus', 'state')); const timestamp = this.safeInteger (transaction, 'createTime'); const txid = this.safeString (transaction, 'txId'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bybit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bybit.js index f74d0db18..7f818c6e3 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bybit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bybit.js @@ -42,6 +42,7 @@ module.exports = class bybit extends Exchange { 'fetchTrades': true, 'fetchTransactions': false, 'fetchWithdrawals': true, + 'fetchPositions': true, }, 'timeframes': { '1m': '1', @@ -73,6 +74,34 @@ module.exports = class bybit extends Exchange { 'referral': 'https://www.bybit.com/app/register?ref=X7Prm', }, 'api': { + 'futures': { + 'private': { + 'get': [ + 'position/list', + 'order/list', + 'order', + 'stop-order/list', + 'stop-order', + 'execution/list', + 'trade/closed-pnl/list', + ], + 'post': [ + 'order/create', + 'order/cancel', + 'order/cancelAll', + 'order/replace', + 'stop-order/create', + 'stop-order/cancel', + 'stop-order/cancelAll', + 'stop-order/replace', + 'position/change-position-margin', + 'position/trading-stop', + 'position/leverage/save', + 'position/switch-mode', + 'position/switch-isolated', + ], + }, + }, 'v2': { 'public': { 'get': [ @@ -286,7 +315,11 @@ module.exports = class bybit extends Exchange { 'LTC/USDT': 'linear', 'XTZ/USDT': 'linear', 'LINK/USDT': 'linear', + 'ADA/USDT': 'linear', + 'DOT/USDT': 'linear', + 'UNI/USDT': 'linear', }, + 'defaultType': 'linear', // may also be inverse or inverseFuture 'code': 'BTC', 'cancelAllOrders': { // 'method': 'v2PrivatePostOrderCancelAll', // v2PrivatePostStopOrderCancelAll @@ -401,8 +434,8 @@ module.exports = class bybit extends Exchange { const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {}); const priceFilter = this.safeValue (market, 'price_filter', {}); const precision = { - 'amount': this.safeFloat (lotSizeFilter, 'qty_step'), - 'price': this.safeFloat (priceFilter, 'tick_size'), + 'amount': this.safeNumber (lotSizeFilter, 'qty_step'), + 'price': this.safeNumber (priceFilter, 'tick_size'), }; const status = this.safeString (market, 'status'); let active = undefined; @@ -416,8 +449,8 @@ module.exports = class bybit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'type': 'future', 'spot': false, 'future': true, @@ -426,12 +459,12 @@ module.exports = class bybit extends Exchange { 'inverse': inverse, 'limits': { 'amount': { - 'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'), - 'max': this.safeFloat (lotSizeFilter, 'max_trading_qty'), + 'min': this.safeNumber (lotSizeFilter, 'min_trading_qty'), + 'max': this.safeNumber (lotSizeFilter, 'max_trading_qty'), }, 'price': { - 'min': this.safeFloat (priceFilter, 'min_price'), - 'max': this.safeFloat (priceFilter, 'max_price'), + 'min': this.safeNumber (priceFilter, 'min_price'), + 'max': this.safeNumber (priceFilter, 'max_price'), }, 'cost': { 'min': undefined, @@ -477,9 +510,9 @@ module.exports = class bybit extends Exchange { const timestamp = undefined; const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const open = this.safeFloat (ticker, 'prev_price_24h'); - let percentage = this.safeFloat (ticker, 'price_24h_pcnt'); + const last = this.safeNumber (ticker, 'last_price'); + const open = this.safeNumber (ticker, 'prev_price_24h'); + let percentage = this.safeNumber (ticker, 'price_24h_pcnt'); if (percentage !== undefined) { percentage *= 100; } @@ -489,18 +522,18 @@ module.exports = class bybit extends Exchange { change = last - open; average = this.sum (open, last) / 2; } - const baseVolume = this.safeFloat (ticker, 'turnover_24h'); - const quoteVolume = this.safeFloat (ticker, 'volume_24h'); + const baseVolume = this.safeNumber (ticker, 'turnover_24h'); + const quoteVolume = this.safeNumber (ticker, 'volume_24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price_24h'), - 'low': this.safeFloat (ticker, 'low_price_24h'), - 'bid': this.safeFloat (ticker, 'bid_price'), + 'high': this.safeNumber (ticker, 'high_price_24h'), + 'low': this.safeNumber (ticker, 'low_price_24h'), + 'bid': this.safeNumber (ticker, 'bid_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask_price'), + 'ask': this.safeNumber (ticker, 'ask_price'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -649,11 +682,11 @@ module.exports = class bybit extends Exchange { // return [ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat2 (ohlcv, 'turnover', 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber2 (ohlcv, 'turnover', 'volume'), ]; } @@ -779,9 +812,9 @@ module.exports = class bybit extends Exchange { const marketId = this.safeString (trade, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat2 (trade, 'qty', 'exec_qty'); - let cost = this.safeFloat (trade, 'exec_value'); - const price = this.safeFloat2 (trade, 'exec_price', 'price'); + const amount = this.safeNumber2 (trade, 'qty', 'exec_qty'); + let cost = this.safeNumber (trade, 'exec_value'); + const price = this.safeNumber2 (trade, 'exec_price', 'price'); if (cost === undefined) { if (amount !== undefined) { if (price !== undefined) { @@ -796,14 +829,14 @@ module.exports = class bybit extends Exchange { const side = this.safeStringLower (trade, 'side'); const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind'); const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker'; - const feeCost = this.safeFloat (trade, 'exec_fee'); + const feeCost = this.safeNumber (trade, 'exec_fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyCode = market['inverse'] ? market['base'] : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'fee_rate'), + 'rate': this.safeNumber (trade, 'fee_rate'), }; } return { @@ -963,12 +996,12 @@ module.exports = class bybit extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['used'] = this.safeFloat (balance, 'used_margin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'used_margin'); + account['total'] = this.safeString (balance, 'equity'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -1095,56 +1128,42 @@ module.exports = class bybit extends Exchange { // const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); - let symbol = undefined; - let base = undefined; + const symbol = market['symbol']; + let feeCurrency = undefined; const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const id = this.safeString2 (order, 'order_id', 'stop_order_id'); const type = this.safeStringLower (order, 'order_type'); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - let average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'qty'); - let cost = this.safeFloat (order, 'cum_exec_value'); - let filled = this.safeFloat (order, 'cum_exec_qty'); - let remaining = this.safeFloat (order, 'leaves_qty'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'qty'); + const cost = this.safeNumber (order, 'cum_exec_value'); + const filled = this.safeNumber (order, 'cum_exec_qty'); + const remaining = this.safeNumber (order, 'leaves_qty'); + const marketTypes = this.safeValue (this.options, 'marketTypes', {}); + const marketType = this.safeString (marketTypes, symbol); if (market !== undefined) { - symbol = market['symbol']; - base = market['base']; + if (marketType === 'linear') { + feeCurrency = market['quote']; + } else { + feeCurrency = market['base']; + } } let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time'); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = amount - remaining; - } - if (filled !== undefined) { - if ((remaining === undefined) && (amount !== undefined)) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if ((type === 'market') && (cost !== undefined) && (cost > 0)) { - price = undefined; - if (average === undefined) { - average = filled / cost; - } - } - } const status = this.parseOrderStatus (this.safeString2 (order, 'order_status', 'stop_order_status')); const side = this.safeStringLower (order, 'side'); - let feeCost = this.safeFloat (order, 'cum_exec_fee'); + let feeCost = this.safeNumber (order, 'cum_exec_fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); fee = { 'cost': feeCost, - 'currency': base, + 'currency': feeCurrency, }; } let clientOrderId = this.safeString (order, 'order_link_id'); @@ -1152,9 +1171,9 @@ module.exports = class bybit extends Exchange { clientOrderId = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); - const stopPrice = this.safeFloat (order, 'stop_px'); + const stopPrice = this.safeNumber (order, 'stop_px'); const postOnly = (timeInForce === 'PO'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1176,7 +1195,7 @@ module.exports = class bybit extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -2027,7 +2046,8 @@ module.exports = class bybit extends Exchange { const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); + const type = this.safeStringLower (transaction, 'type'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -2047,8 +2067,8 @@ module.exports = class bybit extends Exchange { 'tag': undefined, 'tagTo': undefined, 'tagFrom': undefined, - 'type': 'withdrawal', - 'amount': this.safeFloat (transaction, 'amount'), + 'type': type, + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -2131,8 +2151,8 @@ module.exports = class bybit extends Exchange { // const currencyId = this.safeString (item, 'coin'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'wallet_balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'wallet_balance'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -2198,7 +2218,8 @@ module.exports = class bybit extends Exchange { 'recv_window': this.options['recvWindow'], 'timestamp': timestamp, }); - const auth = this.rawencode (this.keysort (query)); + const sortedQuery = this.keysort (query); + const auth = this.rawencode (sortedQuery); const signature = this.hmac (this.encode (auth), this.encode (this.secret)); if (method === 'POST') { body = this.json (this.extend (query, { @@ -2208,7 +2229,7 @@ module.exports = class bybit extends Exchange { 'Content-Type': 'application/json', }; } else { - request += '?' + auth + '&sign=' + signature; + request += '?' + this.urlencode (sortedQuery) + '&sign=' + signature; } } url += request; @@ -2231,12 +2252,43 @@ module.exports = class bybit extends Exchange { // time_now: '1583934106.590436' // } // - const errorCode = this.safeValue (response, 'ret_code'); - if (errorCode !== 0) { + const errorCode = this.safeString (response, 'ret_code'); + if (errorCode !== '0') { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback); this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback); throw new ExchangeError (feedback); // unknown message } } + + async fetchPositions (symbols = undefined, params = {}) { + await this.loadMarkets (); + const request = {}; + if (Array.isArray (symbols)) { + const length = symbols.length; + if (length !== 1) { + throw new ArgumentsRequired (this.id + ' fetchPositions takes exactly one symbol'); + } + request['symbol'] = this.marketId (symbols[0]); + } + const defaultType = this.safeString (this.options, 'defaultType', 'linear'); + const type = this.safeString (params, 'type', defaultType); + params = this.omit (params, 'type'); + let response = undefined; + if (type === 'linear') { + response = await this.privateLinearGetPositionList (this.extend (request, params)); + } else if (type === 'inverse') { + response = await this.v2PrivateGetPositionList (this.extend (request, params)); + } else if (type === 'inverseFuture') { + response = await this.futuresPrivateGetPositionList (this.extend (request, params)); + } + // { + // ret_code: 0, + // ret_msg: 'OK', + // ext_code: '', + // ext_info: '', + // result: [] or {} depending on the request + // } + return this.safeValue (response, 'result'); + } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bytetrade.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bytetrade.js index 25953b6f7..ad0c929d8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bytetrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/bytetrade.js @@ -186,12 +186,12 @@ module.exports = class bytetrade extends Exchange { const limits = this.safeValue (currency, 'limits'); const deposit = this.safeValue (limits, 'deposit'); const amountPrecision = this.safeInteger (currency, 'basePrecision'); - let maxDeposit = this.safeFloat (deposit, 'max'); + let maxDeposit = this.safeNumber (deposit, 'max'); if (maxDeposit === -1.0) { maxDeposit = undefined; } const withdraw = this.safeValue (limits, 'withdraw'); - let maxWithdraw = this.safeFloat (withdraw, 'max'); + let maxWithdraw = this.safeNumber (withdraw, 'max'); if (maxWithdraw === -1.0) { maxWithdraw = undefined; } @@ -207,11 +207,11 @@ module.exports = class bytetrade extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (deposit, 'min'), + 'min': this.safeNumber (deposit, 'min'), 'max': maxDeposit, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'min'), + 'min': this.safeNumber (withdraw, 'min'), 'max': maxWithdraw, }, }, @@ -265,12 +265,12 @@ module.exports = class bytetrade extends Exchange { 'normalSymbol': normalSymbol, 'limits': { 'amount': { - 'min': this.safeFloat (amount, 'min'), - 'max': this.safeFloat (amount, 'max'), + 'min': this.safeNumber (amount, 'min'), + 'max': this.safeNumber (amount, 'max'), }, 'price': { - 'min': this.safeFloat (price, 'min'), - 'max': this.safeFloat (price, 'max'), + 'min': this.safeNumber (price, 'min'), + 'max': this.safeNumber (price, 'max'), }, 'cost': { 'min': undefined, @@ -298,11 +298,11 @@ module.exports = class bytetrade extends Exchange { const currencyId = this.safeString (balance, 'code'); const code = this.safeCurrencyCode (currencyId, undefined); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'used'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'used'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -363,22 +363,22 @@ module.exports = class bytetrade extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), - 'open': this.safeFloat (ticker, 'open'), - 'close': this.safeFloat (ticker, 'close'), - 'last': this.safeFloat (ticker, 'last'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), + 'open': this.safeNumber (ticker, 'open'), + 'close': this.safeNumber (ticker, 'close'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, // previous day close - 'change': this.safeFloat (ticker, 'change'), - 'percentage': this.safeFloat (ticker, 'percentage'), + 'change': this.safeNumber (ticker, 'change'), + 'percentage': this.safeNumber (ticker, 'percentage'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -421,24 +421,16 @@ module.exports = class bytetrade extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidsAsks (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetDepth (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetDepth (params); + return this.parseTickers (response, symbols); } async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const rawTickers = await this.marketGetTickers (params); - return this.parseTickers (rawTickers, symbols); + const response = await this.marketGetTickers (params); + return this.parseTickers (response, symbols); } parseOHLCV (ohlcv, market = undefined) { @@ -454,11 +446,11 @@ module.exports = class bytetrade extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -488,9 +480,9 @@ module.exports = class bytetrade extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeInteger (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - const cost = this.safeFloat (trade, 'cost'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); + const cost = this.safeNumber (trade, 'cost'); const id = this.safeString (trade, 'id'); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'takerOrMaker'); @@ -560,12 +552,12 @@ module.exports = class bytetrade extends Exchange { const timestamp = this.safeInteger (order, 'timestamp'); const datetime = this.safeString (order, 'datetime'); const lastTradeTimestamp = this.safeInteger (order, 'lastTradeTimestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled'); - const remaining = this.safeFloat (order, 'remaining'); - const cost = this.safeFloat (order, 'cost'); - const average = this.safeFloat (order, 'average'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled'); + const remaining = this.safeNumber (order, 'remaining'); + const cost = this.safeNumber (order, 'cost'); + const average = this.safeNumber (order, 'average'); const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); @@ -958,7 +950,7 @@ module.exports = class bytetrade extends Exchange { }; } - async transfer (code, amount, address, message = '', params = {}) { + async transfer (code, amount, fromAccount, toAccount, params = {}) { this.checkRequiredDependencies (); if (this.apiKey === undefined) { throw new ArgumentsRequired ('transfer() requires this.apiKey'); @@ -976,6 +968,7 @@ module.exports = class bytetrade extends Exchange { expirationDatetime = expirationDatetime.split ('.')[0]; const feeAmount = '300000000000000'; const defaultDappId = 'Sagittarius'; + const message = this.safeString (params, 'message', ''); const dappId = this.safeString (params, 'dappId', defaultDappId); const eightBytes = this.integerPow ('2', '64'); const byteStringArray = [ @@ -989,8 +982,8 @@ module.exports = class bytetrade extends Exchange { this.numberToLE (feeAmount, 8), // string for 32 bit php this.numberToLE (this.apiKey.length, 1), this.stringToBinary (this.encode (this.apiKey)), - this.numberToLE (address.length, 1), - this.stringToBinary (this.encode (address)), + this.numberToLE (toAccount.length, 1), + this.stringToBinary (this.encode (toAccount)), this.numberToLE (assetType, 4), this.numberToLE (this.integerDivide (amountChain, eightBytes), 8), this.numberToLE (this.integerModulo (amountChain, eightBytes), 8), @@ -1011,7 +1004,7 @@ module.exports = class bytetrade extends Exchange { const operation = { 'fee': '300000000000000', 'from': this.apiKey, - 'to': address, + 'to': toAccount, 'asset_type': parseInt (currency['id']), 'amount': amountChain.toString (), 'message': message, @@ -1165,9 +1158,9 @@ module.exports = class bytetrade extends Exchange { const datetime = this.safeString (transaction, 'datetime'); const type = this.safeString (transaction, 'type'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const feeInfo = this.safeValue (transaction, 'fee'); - const feeCost = this.safeFloat (feeInfo, 'cost'); + const feeCost = this.safeNumber (feeInfo, 'cost'); const feeCurrencyId = this.safeString (feeInfo, 'code'); const feeCode = this.safeCurrencyCode (feeCurrencyId, currency); const fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/cex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/cex.js index 77473d391..876830762 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/cex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/cex.js @@ -256,7 +256,7 @@ module.exports = class cex extends Exchange { 'fee': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimumCurrencyAmount'), + 'min': this.safeNumber (currency, 'minimumCurrencyAmount'), 'max': undefined, }, 'price': { @@ -268,7 +268,7 @@ module.exports = class cex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimalWithdrawalAmount'), + 'min': this.safeNumber (currency, 'minimalWithdrawalAmount'), 'max': undefined, }, }, @@ -351,15 +351,15 @@ module.exports = class cex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minLotSize'), - 'max': this.safeFloat (market, 'maxLotSize'), + 'min': this.safeNumber (market, 'minLotSize'), + 'max': this.safeNumber (market, 'maxLotSize'), }, 'price': { - 'min': this.safeFloat (market, 'minPrice'), - 'max': this.safeFloat (market, 'maxPrice'), + 'min': this.safeNumber (market, 'minPrice'), + 'max': this.safeNumber (market, 'maxPrice'), }, 'cost': { - 'min': this.safeFloat (market, 'minLotSizeS2'), + 'min': this.safeNumber (market, 'minLotSizeS2'), 'max': undefined, }, }, @@ -380,13 +380,13 @@ module.exports = class cex extends Exchange { const currencyId = currencyIds[i]; const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); + account['free'] = this.safeString (balance, 'available'); // https://github.com/ccxt/ccxt/issues/5484 - account['used'] = this.safeFloat (balance, 'orders', 0.0); + account['used'] = this.safeString (balance, 'orders', '0'); const code = this.safeCurrencyCode (currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -415,11 +415,11 @@ module.exports = class cex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -461,12 +461,12 @@ module.exports = class cex extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const volume = this.safeFloat (ticker, 'volume'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'last'); + const volume = this.safeNumber (ticker, 'volume'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'last'); let symbol = undefined; if (market) { symbol = market['symbol']; @@ -528,8 +528,8 @@ module.exports = class cex extends Exchange { const id = this.safeString (trade, 'tid'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let cost = undefined; if (amount !== undefined) { if (price !== undefined) { @@ -601,8 +601,8 @@ module.exports = class cex extends Exchange { // "complete": false // } // - const placedAmount = this.safeFloat (response, 'amount'); - const remaining = this.safeFloat (response, 'pending'); + const placedAmount = this.safeNumber (response, 'amount'); + const remaining = this.safeNumber (response, 'pending'); const timestamp = this.safeValue (response, 'time'); const complete = this.safeValue (response, 'complete'); const status = complete ? 'closed' : 'open'; @@ -621,7 +621,7 @@ module.exports = class cex extends Exchange { 'side': this.safeString (response, 'type'), 'symbol': symbol, 'status': status, - 'price': this.safeFloat (response, 'price'), + 'price': this.safeNumber (response, 'price'), 'amount': placedAmount, 'cost': undefined, 'average': undefined, @@ -663,42 +663,42 @@ module.exports = class cex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - let amount = this.safeFloat (order, 'amount'); + const price = this.safeNumber (order, 'price'); + let amount = this.safeNumber (order, 'amount'); // sell orders can have a negative amount // https://github.com/ccxt/ccxt/issues/5338 if (amount !== undefined) { amount = Math.abs (amount); } - const remaining = this.safeFloat2 (order, 'pending', 'remains'); + const remaining = this.safeNumber2 (order, 'pending', 'remains'); const filled = amount - remaining; let fee = undefined; let cost = undefined; if (market !== undefined) { symbol = market['symbol']; - const taCost = this.safeFloat (order, 'ta:' + market['quote']); - const ttaCost = this.safeFloat (order, 'tta:' + market['quote']); + const taCost = this.safeNumber (order, 'ta:' + market['quote']); + const ttaCost = this.safeNumber (order, 'tta:' + market['quote']); cost = this.sum (taCost, ttaCost); const baseFee = 'fa:' + market['base']; const baseTakerFee = 'tfa:' + market['base']; const quoteFee = 'fa:' + market['quote']; const quoteTakerFee = 'tfa:' + market['quote']; - let feeRate = this.safeFloat (order, 'tradingFeeMaker'); + let feeRate = this.safeNumber (order, 'tradingFeeMaker'); if (!feeRate) { - feeRate = this.safeFloat (order, 'tradingFeeTaker', feeRate); + feeRate = this.safeNumber (order, 'tradingFeeTaker', feeRate); } if (feeRate) { feeRate /= 100.0; // convert to mathematically-correct percentage coefficients: 1.0 = 100% } if ((baseFee in order) || (baseTakerFee in order)) { - const baseFeeCost = this.safeFloat2 (order, baseFee, baseTakerFee); + const baseFeeCost = this.safeNumber2 (order, baseFee, baseTakerFee); fee = { 'currency': market['base'], 'rate': feeRate, 'cost': baseFeeCost, }; } else if ((quoteFee in order) || (quoteTakerFee in order)) { - const quoteFeeCost = this.safeFloat2 (order, quoteFee, quoteTakerFee); + const quoteFeeCost = this.safeNumber2 (order, quoteFee, quoteTakerFee); fee = { 'currency': market['quote'], 'rate': feeRate, @@ -738,7 +738,7 @@ module.exports = class cex extends Exchange { // ds: 0 } continue; } - const tradePrice = this.safeFloat (item, 'price'); + const tradePrice = this.safeNumber (item, 'price'); if (tradePrice === undefined) { // this represents the order // { @@ -842,8 +842,8 @@ module.exports = class cex extends Exchange { // "fee_amount": "0.03" // } const tradeTimestamp = this.parse8601 (this.safeString (item, 'time')); - const tradeAmount = this.safeFloat (item, 'amount'); - const feeCost = this.safeFloat (item, 'fee_amount'); + const tradeAmount = this.safeNumber (item, 'amount'); + const feeCost = this.safeNumber (item, 'fee_amount'); let absTradeAmount = (tradeAmount < 0) ? -tradeAmount : tradeAmount; let tradeCost = undefined; if (tradeSide === 'sell') { @@ -1188,12 +1188,12 @@ module.exports = class cex extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const side = this.safeString (order, 'type'); - const baseAmount = this.safeFloat (order, 'a:' + baseId + ':cds'); - const quoteAmount = this.safeFloat (order, 'a:' + quoteId + ':cds'); - const fee = this.safeFloat (order, 'f:' + quoteId + ':cds'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const remaining = this.safeFloat (order, 'remains'); + const baseAmount = this.safeNumber (order, 'a:' + baseId + ':cds'); + const quoteAmount = this.safeNumber (order, 'a:' + quoteId + ':cds'); + const fee = this.safeNumber (order, 'f:' + quoteId + ':cds'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const remaining = this.safeNumber (order, 'remains'); const filled = amount - remaining; let orderAmount = undefined; let cost = undefined; @@ -1205,10 +1205,10 @@ module.exports = class cex extends Exchange { cost = quoteAmount; average = orderAmount / cost; } else { - const ta = this.safeFloat (order, 'ta:' + quoteId, 0); - const tta = this.safeFloat (order, 'tta:' + quoteId, 0); - const fa = this.safeFloat (order, 'fa:' + quoteId, 0); - const tfa = this.safeFloat (order, 'tfa:' + quoteId, 0); + const ta = this.safeNumber (order, 'ta:' + quoteId, 0); + const tta = this.safeNumber (order, 'tta:' + quoteId, 0); + const fa = this.safeNumber (order, 'fa:' + quoteId, 0); + const tfa = this.safeNumber (order, 'tfa:' + quoteId, 0); if (side === 'sell') { cost = this.sum (this.sum (ta, tta), this.sum (fa, tfa)); } else { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/chilebit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/chilebit.js deleted file mode 100644 index 4aeeb9ec3..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/chilebit.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const foxbit = require ('./foxbit.js'); - -// --------------------------------------------------------------------------- - -module.exports = class chilebit extends foxbit { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'chilebit', - 'name': 'ChileBit', - 'countries': [ 'CL' ], - 'has': { - 'CORS': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg', - 'api': { - 'public': 'https://api.blinktrade.com/api', - 'private': 'https://api.blinktrade.com/tapi', - }, - 'www': 'https://chilebit.net', - 'doc': 'https://blinktrade.com/docs', - }, - 'options': { - 'brokerId': '9', // https://blinktrade.com/docs/#brokers - }, - }); - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbase.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbase.js index cfceba2a4..1413a7064 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbase.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbase.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, RateLimitExceeded, InvalidNonce } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -411,10 +412,10 @@ module.exports = class coinbase extends Exchange { const timestamp = this.parse8601 (this.safeValue (transaction, 'created_at')); const updated = this.parse8601 (this.safeValue (transaction, 'updated_at')); const type = this.safeString (transaction, 'resource'); - const amount = this.safeFloat (subtotalObject, 'amount'); + const amount = this.safeNumber (subtotalObject, 'amount'); const currencyId = this.safeString (subtotalObject, 'currency'); const currency = this.safeCurrencyCode (currencyId); - const feeCost = this.safeFloat (feeObject, 'amount'); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -490,15 +491,12 @@ module.exports = class coinbase extends Exchange { const orderId = undefined; const side = this.safeString (trade, 'resource'); const type = undefined; - const cost = this.safeFloat (subtotalObject, 'amount'); - const amount = this.safeFloat (amountObject, 'amount'); - let price = undefined; - if (cost !== undefined) { - if ((amount !== undefined) && (amount > 0)) { - price = cost / amount; - } - } - const feeCost = this.safeFloat (feeObject, 'amount'); + const costString = this.safeString (subtotalObject, 'amount'); + const amountString = this.safeString (amountObject, 'amount'); + const cost = this.parseNumber (costString); + const amount = this.parseNumber (amountString); + const price = this.parseNumber (Precise.stringDiv (costString, amountString)); + const feeCost = this.safeNumber (feeObject, 'amount'); const feeCurrencyId = this.safeString (feeObject, 'currency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); const fee = { @@ -566,7 +564,7 @@ module.exports = class coinbase extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (quoteCurrency, 'min_size'), + 'min': this.safeNumber (quoteCurrency, 'min_size'), 'max': undefined, }, }, @@ -648,7 +646,7 @@ module.exports = class coinbase extends Exchange { 'precision': undefined, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min_size'), + 'min': this.safeNumber (currency, 'min_size'), 'max': undefined, }, 'price': { @@ -679,9 +677,9 @@ module.exports = class coinbase extends Exchange { const buy = await this.publicGetPricesSymbolBuy (request); const sell = await this.publicGetPricesSymbolSell (request); const spot = await this.publicGetPricesSymbolSpot (request); - const ask = this.safeFloat (buy['data'], 'amount'); - const bid = this.safeFloat (sell['data'], 'amount'); - const last = this.safeFloat (spot['data'], 'amount'); + const ask = this.safeNumber (buy['data'], 'amount'); + const bid = this.safeNumber (sell['data'], 'amount'); + const last = this.safeNumber (spot['data'], 'amount'); return { 'symbol': symbol, 'timestamp': timestamp, @@ -724,7 +722,7 @@ module.exports = class coinbase extends Exchange { if (this.inArray (balance['type'], accounts)) { const currencyId = this.safeString (balance['balance'], 'currency'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (balance['balance'], 'amount'); + const total = this.safeNumber (balance['balance'], 'amount'); const free = total; const used = undefined; if (code in result) { @@ -1025,7 +1023,7 @@ module.exports = class coinbase extends Exchange { // } // const amountInfo = this.safeValue (item, 'amount', {}); - let amount = this.safeFloat (amountInfo, 'amount'); + let amount = this.safeNumber (amountInfo, 'amount'); let direction = undefined; if (amount < 0) { direction = 'out'; @@ -1051,7 +1049,7 @@ module.exports = class coinbase extends Exchange { if (feeInfo !== undefined) { const feeCurrencyId = this.safeString (feeInfo, 'currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId, currency); - const feeAmount = this.safeFloat (feeInfo, 'amount'); + const feeAmount = this.safeNumber (feeInfo, 'amount'); fee = { 'cost': feeAmount, 'currency': feeCurrencyCode, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbasepro.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbasepro.js index 582c03a61..6d8c48454 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbasepro.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinbasepro.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound, OnMaintenance, PermissionDenied, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -239,7 +240,7 @@ module.exports = class coinbasepro extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const details = this.safeValue (currency, 'details', {}); - const precision = this.safeFloat (currency, 'max_precision'); + const precision = this.safeNumber (currency, 'max_precision'); const status = this.safeString (currency, 'status'); const active = (status === 'online'); result[code] = { @@ -253,7 +254,7 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (details, 'min_size'), + 'min': this.safeNumber (details, 'min_size'), 'max': undefined, }, 'price': { @@ -265,7 +266,7 @@ module.exports = class coinbasepro extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (details, 'min_withdrawal_amount'), + 'min': this.safeNumber (details, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -309,12 +310,12 @@ module.exports = class coinbasepro extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const priceLimits = { - 'min': this.safeFloat (market, 'quote_increment'), + 'min': this.safeNumber (market, 'quote_increment'), 'max': undefined, }; const precision = { - 'amount': this.safeFloat (market, 'base_increment'), - 'price': this.safeFloat (market, 'quote_increment'), + 'amount': this.safeNumber (market, 'base_increment'), + 'price': this.safeNumber (market, 'quote_increment'), }; const status = this.safeString (market, 'status'); const active = (status === 'online'); @@ -328,13 +329,13 @@ module.exports = class coinbasepro extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'base_min_size'), - 'max': this.safeFloat (market, 'base_max_size'), + 'min': this.safeNumber (market, 'base_min_size'), + 'max': this.safeNumber (market, 'base_max_size'), }, 'price': priceLimits, 'cost': { - 'min': this.safeFloat (market, 'min_market_funds'), - 'max': this.safeFloat (market, 'max_market_funds'), + 'min': this.safeNumber (market, 'min_market_funds'), + 'max': this.safeNumber (market, 'max_market_funds'), }, }, 'active': active, @@ -391,14 +392,13 @@ module.exports = class coinbasepro extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'hold'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'hold'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -455,29 +455,29 @@ module.exports = class coinbasepro extends Exchange { // } // const timestamp = this.parse8601 (this.safeValue (ticker, 'time')); - const bid = this.safeFloat (ticker, 'bid'); - const ask = this.safeFloat (ticker, 'ask'); - const last = this.safeFloat (ticker, 'price'); + const bid = this.safeNumber (ticker, 'bid'); + const ask = this.safeNumber (ticker, 'ask'); + const last = this.safeNumber (ticker, 'price'); const symbol = (market === undefined) ? undefined : market['symbol']; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': undefined, 'ask': ask, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -550,7 +550,7 @@ module.exports = class coinbasepro extends Exchange { if (market !== undefined) { const feeCurrencyId = this.safeStringLower (market, 'quoteId'); const costField = feeCurrencyId + '_value'; - cost = this.safeFloat (trade, costField); + cost = this.safeNumber (trade, costField); feeCurrency = market['quote']; const liquidity = this.safeString (trade, 'liquidity'); if (liquidity !== undefined) { @@ -558,7 +558,7 @@ module.exports = class coinbasepro extends Exchange { feeRate = market[takerOrMaker]; } } - const feeCost = this.safeFloat2 (trade, 'fill_fees', 'fee'); + const feeCost = this.safeNumber2 (trade, 'fill_fees', 'fee'); const fee = { 'cost': feeCost, 'currency': feeCurrency, @@ -572,10 +572,12 @@ module.exports = class coinbasepro extends Exchange { if (orderId !== undefined) { side = (trade['side'] === 'buy') ? 'buy' : 'sell'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - cost = amount * price; + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -637,11 +639,11 @@ module.exports = class coinbasepro extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -721,17 +723,11 @@ module.exports = class coinbasepro extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'filled_size'); - const amount = this.safeFloat (order, 'size', filled); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'executed_value'); - const feeCost = this.safeFloat (order, 'fill_fees'); + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'filled_size'); + const amount = this.safeNumber (order, 'size', filled); + const cost = this.safeNumber (order, 'executed_value'); + const feeCost = this.safeNumber (order, 'fill_fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrencyCode = undefined; @@ -749,9 +745,9 @@ module.exports = class coinbasepro extends Exchange { const side = this.safeString (order, 'side'); const timeInForce = this.safeString (order, 'time_in_force'); const postOnly = this.safeValue (order, 'post_only'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); const clientOrderId = this.safeString (order, 'client_oid'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -769,11 +765,11 @@ module.exports = class coinbasepro extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -863,7 +859,7 @@ module.exports = class coinbasepro extends Exchange { request['client_oid'] = clientOrderId; params = this.omit (params, [ 'clientOrderId', 'client_oid' ]); } - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop_price'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stop_price'); if (stopPrice !== undefined) { request['stop_price'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, [ 'stopPrice', 'stop_price' ]); @@ -877,7 +873,7 @@ module.exports = class coinbasepro extends Exchange { request['price'] = this.priceToPrecision (symbol, price); request['size'] = this.amountToPrecision (symbol, amount); } else if (type === 'market') { - let cost = this.safeFloat2 (params, 'cost', 'funds'); + let cost = this.safeNumber2 (params, 'cost', 'funds'); if (cost === undefined) { if (price !== undefined) { cost = amount * price; @@ -948,19 +944,6 @@ module.exports = class coinbasepro extends Exchange { return await this.privateDeleteOrders (this.extend (request, params)); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - const cost = amount * price; - const currency = market['quote']; - return { - 'type': takerOrMaker, - 'currency': currency, - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (currency, rate * cost)), - }; - } - async fetchPaymentMethods (params = {}) { return await this.privateGetPaymentMethods (params); } @@ -1099,7 +1082,7 @@ module.exports = class coinbasepro extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (transaction); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let type = this.safeString (transaction, 'type'); let address = this.safeString (details, 'crypto_address'); const tag = this.safeString (details, 'destination_tag'); @@ -1108,7 +1091,7 @@ module.exports = class coinbasepro extends Exchange { if (type === 'withdraw') { type = 'withdrawal'; address = this.safeString (details, 'sent_to_address', address); - const feeCost = this.safeFloat (details, 'fee'); + const feeCost = this.safeNumber (details, 'fee'); if (feeCost !== undefined) { if (amount !== undefined) { amount -= feeCost; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coincheck.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coincheck.js index 807882d02..e7a3db265 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coincheck.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coincheck.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -127,12 +128,12 @@ module.exports = class coincheck extends Exchange { if (currencyId in balances) { const account = this.account (); const reserved = currencyId + '_reserved'; - account['free'] = this.safeFloat (balances, currencyId); - account['used'] = this.safeFloat (balances, reserved); + account['free'] = this.safeString (balances, currencyId); + account['used'] = this.safeString (balances, reserved); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -170,23 +171,13 @@ module.exports = class coincheck extends Exchange { const id = this.safeString (order, 'id'); const side = this.safeString (order, 'order_type'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const amount = this.safeFloat (order, 'pending_amount'); - const remaining = this.safeFloat (order, 'pending_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = Math.max (amount - remaining, 0); - if (price !== undefined) { - cost = filled * price; - } - } - } + const amount = this.safeNumber (order, 'pending_amount'); + const remaining = this.safeNumber (order, 'pending_amount'); + const price = this.safeNumber (order, 'rate'); const status = undefined; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -194,7 +185,7 @@ module.exports = class coincheck extends Exchange { 'lastTradeTimestamp': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'side': side, 'type': undefined, 'timeInForce': undefined, @@ -203,12 +194,12 @@ module.exports = class coincheck extends Exchange { 'symbol': symbol, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'info': order, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -232,16 +223,16 @@ module.exports = class coincheck extends Exchange { }; const ticker = await this.publicGetTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -251,7 +242,7 @@ module.exports = class coincheck extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -260,7 +251,7 @@ module.exports = class coincheck extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'rate'); + const priceString = this.safeString (trade, 'rate'); const marketId = this.safeString (trade, 'pair'); market = this.safeValue (this.markets_by_id, marketId, market); let symbol = undefined; @@ -287,7 +278,7 @@ module.exports = class coincheck extends Exchange { } } let takerOrMaker = undefined; - let amount = undefined; + let amountString = undefined; let cost = undefined; let side = undefined; let fee = undefined; @@ -299,24 +290,22 @@ module.exports = class coincheck extends Exchange { takerOrMaker = 'maker'; } const funds = this.safeValue (trade, 'funds', {}); - amount = this.safeFloat (funds, baseId); - cost = this.safeFloat (funds, quoteId); + amountString = this.safeString (funds, baseId); + cost = this.safeNumber (funds, quoteId); fee = { 'currency': this.safeString (trade, 'fee_currency'), - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), }; side = this.safeString (trade, 'side'); orderId = this.safeString (trade, 'order_id'); } else { - amount = this.safeFloat (trade, 'amount'); + amountString = this.safeString (trade, 'amount'); side = this.safeString (trade, 'order_type'); } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'id': id, @@ -387,6 +376,10 @@ module.exports = class coincheck extends Exchange { return await this.privateDeleteExchangeOrdersId (this.extend (request, params)); } + nonce () { + return this.milliseconds (); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { let url = this.urls['api'] + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinegg.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinegg.js index e270e3bf7..0b2e2ef89 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinegg.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinegg.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InvalidNonce, InsufficientFunds, InvalidOrder, OrderNotFound, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -214,8 +215,8 @@ module.exports = class coinegg extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; let change = undefined; let average = undefined; @@ -229,11 +230,11 @@ module.exports = class coinegg extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -243,8 +244,8 @@ module.exports = class coinegg extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVol'), 'info': ticker, }; } @@ -273,15 +274,12 @@ module.exports = class coinegg extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = this.costToPrecision (symbol, price * amount); - } - } const type = 'limit'; const side = this.safeString (trade, 'type'); const id = this.safeString (trade, 'tid'); @@ -328,9 +326,9 @@ module.exports = class coinegg extends Exchange { result[code] = this.account (); } const type = (accountType === 'lock') ? 'used' : 'free'; - result[code][type] = this.safeFloat (balances, key); + result[code][type] = this.safeString (balances, key); } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -339,15 +337,9 @@ module.exports = class coinegg extends Exchange { symbol = market['symbol']; } const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount_original'); - const remaining = this.safeFloat (order, 'amount_outstanding'); - let filled = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount_original'); + const remaining = this.safeNumber (order, 'amount_outstanding'); let status = this.safeString (order, 'status'); if (status === 'cancelled') { status = 'canceled'; @@ -358,7 +350,7 @@ module.exports = class coinegg extends Exchange { const type = 'limit'; const side = this.safeString (order, 'type'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -374,13 +366,13 @@ module.exports = class coinegg extends Exchange { 'stopPrice': undefined, 'cost': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'trades': undefined, 'fee': undefined, 'info': info, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinex.js index cc344ee72..575d0f239 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, OrderNotFound, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -196,13 +197,13 @@ module.exports = class coinex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': this.safeFloat (market, 'taker_fee_rate'), - 'maker': this.safeFloat (market, 'maker_fee_rate'), + 'taker': this.safeNumber (market, 'taker_fee_rate'), + 'maker': this.safeNumber (market, 'maker_fee_rate'), 'info': market, 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -222,16 +223,16 @@ module.exports = class coinex extends Exchange { symbol = market['symbol']; } ticker = this.safeValue (ticker, 'ticker', {}); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -241,7 +242,7 @@ module.exports = class coinex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat2 (ticker, 'vol', 'volume'), + 'baseVolume': this.safeNumber2 (ticker, 'vol', 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -301,16 +302,18 @@ module.exports = class coinex extends Exchange { } const tradeId = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market); - let cost = this.safeFloat (trade, 'deal_money'); - if (!cost) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); + let cost = this.safeNumber (trade, 'deal_money'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_asset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -363,11 +366,11 @@ module.exports = class coinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -428,11 +431,11 @@ module.exports = class coinex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -471,11 +474,11 @@ module.exports = class coinex extends Exchange { // } // const timestamp = this.safeTimestamp (order, 'create_time'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'deal_money'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'deal_amount'); - const average = this.safeFloat (order, 'avg_price'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'deal_money'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'deal_amount'); + const average = this.safeNumber (order, 'avg_price'); let symbol = undefined; const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); @@ -487,11 +490,11 @@ module.exports = class coinex extends Exchange { feeCurrency = market['quote']; } } - const remaining = this.safeFloat (order, 'left'); + const remaining = this.safeNumber (order, 'left'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -513,10 +516,10 @@ module.exports = class coinex extends Exchange { 'trades': undefined, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'deal_fee'), + 'cost': this.safeNumber (order, 'deal_fee'), }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -762,8 +765,8 @@ module.exports = class coinex extends Exchange { const timestamp = this.safeTimestamp (transaction, 'create_time'); const type = ('coin_withdraw_id' in transaction) ? 'withdraw' : 'deposit'; const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); - let feeCost = this.safeFloat (transaction, 'tx_fee'); + let amount = this.safeNumber (transaction, 'amount'); + let feeCost = this.safeNumber (transaction, 'tx_fee'); if (type === 'deposit') { feeCost = 0; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfalcon.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfalcon.js index 6c264b4ec..8d3077293 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfalcon.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfalcon.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, RateLimitExceeded, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -136,11 +137,11 @@ module.exports = class coinfalcon extends Exchange { 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'change_in_24h'), + 'change': this.safeNumber (ticker, 'change_in_24h'), 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -177,20 +178,17 @@ module.exports = class coinfalcon extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const symbol = market['symbol']; - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } const tradeId = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'order_id'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = this.safeString (trade, 'fee_currency_code'); fee = { @@ -258,14 +256,13 @@ module.exports = class coinfalcon extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency_code'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available_balance'), - 'used': this.safeFloat (balance, 'hold_balance'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available_balance'); + account['used'] = this.safeString (balance, 'hold_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -300,19 +297,9 @@ module.exports = class coinfalcon extends Exchange { const marketId = this.safeString (order, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'size_filled'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (price !== undefined) { - cost = filled * price; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'size_filled'); const status = this.parseOrderStatus (this.safeString (order, 'status')); let type = this.safeString (order, 'operation_type'); if (type !== undefined) { @@ -321,7 +308,7 @@ module.exports = class coinfalcon extends Exchange { } const side = this.safeString (order, 'order_type'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -334,16 +321,16 @@ module.exports = class coinfalcon extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'lastTradeTimestamp': undefined, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfloor.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfloor.js index 7fff650de..790ac8c50 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfloor.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinfloor.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { InsufficientFunds, ExchangeError, InvalidNonce, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -105,14 +106,14 @@ module.exports = class coinfloor extends Exchange { const baseIdLower = this.safeStringLower (market, 'baseId'); const quoteIdLower = this.safeStringLower (market, 'quoteId'); result[base] = { - 'free': this.safeFloat (response, baseIdLower + '_available'), - 'used': this.safeFloat (response, baseIdLower + '_reserved'), - 'total': this.safeFloat (response, baseIdLower + '_balance'), + 'free': this.safeNumber (response, baseIdLower + '_available'), + 'used': this.safeNumber (response, baseIdLower + '_reserved'), + 'total': this.safeNumber (response, baseIdLower + '_balance'), }; result[quote] = { - 'free': this.safeFloat (response, quoteIdLower + '_available'), - 'used': this.safeFloat (response, quoteIdLower + '_reserved'), - 'total': this.safeFloat (response, quoteIdLower + '_balance'), + 'free': this.safeNumber (response, quoteIdLower + '_available'), + 'used': this.safeNumber (response, quoteIdLower + '_reserved'), + 'total': this.safeNumber (response, quoteIdLower + '_balance'), }; return this.parseBalance (result); } @@ -133,22 +134,22 @@ module.exports = class coinfloor extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -177,14 +178,11 @@ module.exports = class coinfloor extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -302,8 +300,8 @@ module.exports = class coinfloor extends Exchange { const parts = key.split ('_'); const numParts = parts.length; if (numParts === 2) { - const tmpBaseAmount = this.safeFloat (item, parts[0]); - const tmpQuoteAmount = this.safeFloat (item, parts[1]); + const tmpBaseAmount = this.safeNumber (item, parts[0]); + const tmpQuoteAmount = this.safeNumber (item, parts[1]); if (tmpBaseAmount !== undefined && tmpQuoteAmount !== undefined) { baseId = parts[0]; quoteId = parts[1]; @@ -319,7 +317,7 @@ module.exports = class coinfloor extends Exchange { const referenceId = this.safeString (item, 'id'); const timestamp = this.parse8601 (this.safeString (item, 'datetime')); let fee = undefined; - const feeCost = this.safeFloat (item, 'fee'); + const feeCost = this.safeNumber (item, 'fee'); const result = { 'id': undefined, 'timestamp': timestamp, @@ -423,8 +421,8 @@ module.exports = class coinfloor extends Exchange { 'datetime': this.iso8601 (timestamp), 'timestamp': timestamp, 'type': type, - 'price': this.safeFloat (response, 'price'), - 'remaining': this.safeFloat (response, 'amount'), + 'price': this.safeNumber (response, 'price'), + 'remaining': this.safeNumber (response, 'amount'), 'info': response, }; } @@ -449,19 +447,14 @@ module.exports = class coinfloor extends Exchange { parseOrder (order, market = undefined) { const timestamp = this.parse8601 (this.safeString (order, 'datetime')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); let side = undefined; const status = this.safeString (order, 'status'); - if (order['type'] === 0) { + const rawType = this.safeString (order, 'type'); + if (rawType === '0') { side = 'buy'; - } else if (order['type'] === 1) { + } else if (rawType === '1') { side = 'sell'; } let symbol = undefined; @@ -469,7 +462,7 @@ module.exports = class coinfloor extends Exchange { symbol = market['symbol']; } const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -487,11 +480,11 @@ module.exports = class coinfloor extends Exchange { 'amount': undefined, 'filled': undefined, 'remaining': amount, - 'cost': cost, + 'cost': undefined, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coingi.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coingi.js index 650d80885..931325ea6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coingi.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coingi.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -165,14 +166,14 @@ module.exports = class coingi extends Exchange { const currencyId = this.safeString (balance['currency'], 'name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - const blocked = this.safeFloat (balance, 'blocked'); - const inOrders = this.safeFloat (balance, 'inOrders'); - const withdrawing = this.safeFloat (balance, 'withdrawing'); - account['used'] = this.sum (blocked, inOrders, withdrawing); + account['free'] = this.safeString (balance, 'available'); + const blocked = this.safeString (balance, 'blocked'); + const inOrders = this.safeString (balance, 'inOrders'); + const withdrawing = this.safeString (balance, 'withdrawing'); + account['used'] = Precise.stringAdd (Precise.stringAdd (blocked, inOrders), withdrawing); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = 512, params = {}) { @@ -198,11 +199,11 @@ module.exports = class coingi extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -212,8 +213,8 @@ module.exports = class coingi extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'counterVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'counterVolume'), 'info': ticker, }; } @@ -246,14 +247,11 @@ module.exports = class coingi extends Exchange { } parseTrade (trade, market = undefined) { - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const timestamp = this.safeInteger (trade, 'timestamp'); const id = this.safeString (trade, 'id'); const marketId = this.safeString (trade, 'currencyPair'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmarketcap.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmarketcap.js index 171a65889..85edd4882 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmarketcap.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmarketcap.js @@ -208,16 +208,16 @@ module.exports = class coinmarketcap extends Exchange { if (timestamp === undefined) { timestamp = this.milliseconds (); } - const change = this.safeFloat (ticker, 'percent_change_24h'); + const change = this.safeNumber (ticker, 'percent_change_24h'); let last = undefined; let symbol = undefined; let volume = undefined; if (market !== undefined) { symbol = market['symbol']; const priceKey = 'price_' + market['quoteId']; - last = this.safeFloat (ticker, priceKey); + last = this.safeNumber (ticker, priceKey); const volumeKey = '24h_volume_' + market['quoteId']; - volume = this.safeFloat (ticker, volumeKey); + volume = this.safeNumber (ticker, volumeKey); } return { 'symbol': symbol, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmate.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmate.js index b03ce8783..821e5d7e8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmate.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinmate.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder, OrderNotFound, RateLimitExceeded, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -230,7 +231,7 @@ module.exports = class coinmate extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -258,12 +259,12 @@ module.exports = class coinmate extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -286,16 +287,16 @@ module.exports = class coinmate extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'data'); const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'vwap': undefined, 'askVolume': undefined, 'open': undefined, @@ -305,7 +306,7 @@ module.exports = class coinmate extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'amount'), + 'baseVolume': this.safeNumber (ticker, 'amount'), 'quoteVolume': undefined, 'info': ticker, }; @@ -374,8 +375,8 @@ module.exports = class coinmate extends Exchange { // } // const timestamp = this.safeInteger (item, 'timestamp'); - const amount = this.safeFloat (item, 'amount'); - const fee = this.safeFloat (item, 'fee'); + const amount = this.safeNumber (item, 'amount'); + const fee = this.safeNumber (item, 'fee'); const txid = this.safeString (item, 'txid'); const address = this.safeString (item, 'destination'); const tag = this.safeString (item, 'destinationTag'); @@ -453,21 +454,18 @@ module.exports = class coinmate extends Exchange { // const marketId = this.safeString (trade, 'currencyPair'); market = this.safeMarket (marketId, market, '_'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeStringLower2 (trade, 'type', 'tradeType'); const type = this.safeStringLower (trade, 'orderType'); const orderId = this.safeString (trade, 'orderId'); const id = this.safeString (trade, 'transactionId'); const timestamp = this.safeInteger2 (trade, 'timestamp', 'createdTimestamp'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -608,11 +606,11 @@ module.exports = class coinmate extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.safeInteger (order, 'timestamp'); const side = this.safeStringLower (order, 'type'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'originalAmount'); - let remaining = this.safeFloat (order, 'remainingAmount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'originalAmount'); + let remaining = this.safeNumber (order, 'remainingAmount'); if (remaining === undefined) { - remaining = this.safeFloat (order, 'amount'); + remaining = this.safeNumber (order, 'amount'); } let status = this.parseOrderStatus (this.safeString (order, 'status')); const type = this.parseOrderType (this.safeString (order, 'orderTradeType')); @@ -627,11 +625,11 @@ module.exports = class coinmate extends Exchange { cost = filled * price; } } - const average = this.safeFloat (order, 'avgPrice'); + const average = this.safeNumber (order, 'avgPrice'); const marketId = this.safeString (order, 'currencyPair'); const symbol = this.safeSymbol (marketId, market, '_'); const clientOrderId = this.safeString (order, 'clientOrderId'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); return { 'id': id, 'clientOrderId': clientOrderId, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinone.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinone.js index 0c86365b6..cd0f3585c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinone.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinone.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, BadRequest, ExchangeError, ArgumentsRequired, OrderNotFound, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -142,11 +143,11 @@ module.exports = class coinone extends Exchange { const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'avail'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -199,13 +200,13 @@ module.exports = class coinone extends Exchange { parseTicker (ticker, market = undefined) { const timestamp = this.safeTimestamp (ticker, 'timestamp'); - const first = this.safeFloat (ticker, 'first'); - const last = this.safeFloat (ticker, 'last'); + const first = this.safeNumber (ticker, 'first'); + const last = this.safeNumber (ticker, 'last'); let average = undefined; if (first !== undefined && last !== undefined) { average = this.sum (first, last) / 2; } - const previousClose = this.safeFloat (ticker, 'yesterday_last'); + const previousClose = this.safeNumber (ticker, 'yesterday_last'); let change = undefined; let percentage = undefined; if (last !== undefined && previousClose !== undefined) { @@ -219,8 +220,8 @@ module.exports = class coinone extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -233,7 +234,7 @@ module.exports = class coinone extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -279,20 +280,17 @@ module.exports = class coinone extends Exchange { side = 'buy'; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'fee'); + let feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); - let feeRate = this.safeFloat (trade, 'feeRate'); + let feeRate = this.safeNumber (trade, 'feeRate'); feeRate = Math.abs (feeRate); let feeCurrencyCode = undefined; if (market !== undefined) { @@ -452,7 +450,7 @@ module.exports = class coinone extends Exchange { // } // const id = this.safeString (order, 'orderId'); - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); const timestamp = this.safeTimestamp (order, 'timestamp'); let side = this.safeString (order, 'type'); if (side === 'ask') { @@ -460,9 +458,8 @@ module.exports = class coinone extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const remaining = this.safeFloat (order, 'remainQty'); - let filled = undefined; - const amount = this.safeFloat (order, 'qty'); + const remaining = this.safeNumber (order, 'remainQty'); + const amount = this.safeNumber (order, 'qty'); let status = this.safeString (order, 'status'); // https://github.com/ccxt/ccxt/pull/7067 if (status === 'live') { @@ -472,14 +469,7 @@ module.exports = class coinone extends Exchange { } } } - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (amount - remaining); - } status = this.parseOrderStatus (status); - let cost = undefined; - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } let symbol = undefined; let base = undefined; let quote = undefined; @@ -499,16 +489,16 @@ module.exports = class coinone extends Exchange { quote = market['quote']; } let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = (side === 'sell') ? quote : base; fee = { 'cost': feeCost, - 'rate': this.safeFloat (order, 'feeRate'), + 'rate': this.safeNumber (order, 'feeRate'), 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -522,15 +512,15 @@ module.exports = class coinone extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': amount, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -605,8 +595,8 @@ module.exports = class coinone extends Exchange { // eslint-disable-next-line quotes throw new ArgumentsRequired (this.id + " cancelOrder() requires a symbol argument. To cancel the order, pass a symbol argument and {'price': 12345, 'qty': 1.2345, 'is_ask': 0} in the params argument of cancelOrder."); } - const price = this.safeFloat (params, 'price'); - const qty = this.safeFloat (params, 'qty'); + const price = this.safeNumber (params, 'price'); + const qty = this.safeNumber (params, 'qty'); const isAsk = this.safeInteger (params, 'is_ask'); if ((price === undefined) || (qty === undefined) || (isAsk === undefined)) { // eslint-disable-next-line quotes diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinspot.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinspot.js index e04c42b5d..63c9b3fd2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinspot.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/coinspot.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -123,7 +124,7 @@ module.exports = class coinspot extends Exchange { const balance = currencies[currencyId]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } } @@ -133,11 +134,11 @@ module.exports = class coinspot extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -157,16 +158,16 @@ module.exports = class coinspot extends Exchange { id = id.toLowerCase (); const ticker = response['prices'][id]; const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -214,11 +215,13 @@ module.exports = class coinspot extends Exchange { // "market":"BTC/AUD" // } // - const price = this.safeFloat (trade, 'rate'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'total'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger (trade, 'solddate'); const marketId = this.safeString (trade, 'market'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/crex24.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/crex24.js index 7c1298090..5c3a3ccde 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/crex24.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/crex24.js @@ -4,6 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, InvalidNonce, RequestTimeout, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, AuthenticationError, BadSymbol } = require ('./base/errors'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -110,6 +112,7 @@ module.exports = class crex24 extends Exchange { ], }, }, + 'precisionMode': TICK_SIZE, 'fees': { 'trading': { 'tierBased': true, @@ -130,6 +133,7 @@ module.exports = class crex24 extends Exchange { 'BIT': 'BitMoney', 'BULL': 'BuySell', 'CREDIT': 'TerraCredit', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'GHOST': 'GHOSTPRISM', 'IQ': 'IQ.Cash', 'PUT': 'PutinCoin', @@ -163,6 +167,7 @@ module.exports = class crex24 extends Exchange { 'API Key': AuthenticationError, // "API Key '9edc48de-d5b0-4248-8e7e-f59ffcd1c7f1' doesn't exist." 'Insufficient funds': InsufficientFunds, // "Insufficient funds: new order requires 10 ETH which is more than the available balance." 'has been delisted.': BadSymbol, // {"errorDescription":"Instrument '$PAC-BTC' has been delisted."} + 'is currently suspended.': BadSymbol, // {"errorDescription":"Trading in BITG-BTC is currently suspended."} 'Mandatory parameter': BadRequest, // {"errorDescription":"Mandatory parameter 'feeCurrency' is missing."} }, }, @@ -204,12 +209,12 @@ module.exports = class crex24 extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const tickSize = this.safeValue (market, 'tickSize'); - const minPrice = this.safeValue (market, 'minPrice'); - const minAmount = this.safeFloat (market, 'minVolume'); + const tickSize = this.safeNumber (market, 'tickSize'); + const minPrice = this.safeNumber (market, 'minPrice'); + const minAmount = this.safeNumber (market, 'minVolume'); const precision = { - 'amount': this.precisionFromString (this.numberToString (minAmount)), - 'price': this.precisionFromString (this.numberToString (tickSize)), + 'amount': minAmount, + 'price': tickSize, }; const active = (market['state'] === 'active'); result.push ({ @@ -274,7 +279,8 @@ module.exports = class crex24 extends Exchange { const currency = response[i]; const id = this.safeString (currency, 'symbol'); const code = this.safeCurrencyCode (id); - const precision = this.safeInteger (currency, 'withdrawalPrecision'); + const withdrawalPrecision = this.safeInteger (currency, 'withdrawalPrecision'); + const precision = Math.pow (10, -withdrawalPrecision); const address = this.safeValue (currency, 'BaseAddress'); const active = (currency['depositsAllowed'] && currency['withdrawalsAllowed'] && !currency['isDelisted']); const type = currency['isFiat'] ? 'fiat' : 'crypto'; @@ -286,7 +292,7 @@ module.exports = class crex24 extends Exchange { 'type': type, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'flatWithdrawalFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'flatWithdrawalFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -302,12 +308,12 @@ module.exports = class crex24 extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'minDeposit'), + 'min': this.safeNumber (currency, 'minDeposit'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -337,11 +343,11 @@ module.exports = class crex24 extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -393,16 +399,16 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); const marketId = this.safeString (ticker, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -410,10 +416,10 @@ module.exports = class crex24 extends Exchange { 'last': last, 'previousClose': undefined, // previous day close 'change': undefined, - 'percentage': this.safeFloat (ticker, 'percentChange'), + 'percentage': this.safeNumber (ticker, 'percentChange'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'baseVolume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'baseVolume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -483,14 +489,6 @@ module.exports = class crex24 extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - parseTrade (trade, market = undefined) { // // public fetchTrades @@ -515,14 +513,11 @@ module.exports = class crex24 extends Exchange { // } // const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeString (trade, 'side'); const orderId = this.safeString (trade, 'orderId'); @@ -531,7 +526,7 @@ module.exports = class crex24 extends Exchange { let fee = undefined; const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCode = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -592,11 +587,11 @@ module.exports = class crex24 extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -665,50 +660,19 @@ module.exports = class crex24 extends Exchange { const marketId = this.safeString (order, 'instrument'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'timestamp')); - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remainingVolume'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remainingVolume'); const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'lastUpdate')); - let cost = undefined; - if (remaining !== undefined) { - if (amount !== undefined) { - filled = amount - remaining; - if (this.options['parseOrderToPrecision']) { - filled = parseFloat (this.amountToPrecision (symbol, filled)); - } - filled = Math.max (filled, 0.0); - if (price !== undefined) { - cost = price * filled; - } - } - } const id = this.safeString (order, 'id'); const type = this.safeString (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeString (order, 'side'); const fee = undefined; const trades = undefined; - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } - } + const average = undefined; const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -722,14 +686,14 @@ module.exports = class crex24 extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -764,7 +728,7 @@ module.exports = class crex24 extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order'); } else { @@ -1183,8 +1147,8 @@ module.exports = class crex24 extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'createdAt')); const updated = this.parse8601 (this.safeString (transaction, 'processedAt')); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); const fee = { 'cost': feeCost, 'currency': code, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/currencycom.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/currencycom.js index c8570f1d4..17aa6bfa5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/currencycom.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/currencycom.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, BadRequest } = require ('./base/errors'); -const { ROUND, TICK_SIZE } = require ('./base/functions/number'); +const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -92,6 +93,7 @@ module.exports = class currencycom extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.002, @@ -250,7 +252,7 @@ module.exports = class currencycom extends Exchange { const filtersByType = this.indexBy (filters, 'filterType'); const precision = { 'amount': 1 / Math.pow (1, this.safeInteger (market, 'baseAssetPrecision')), - 'price': this.safeFloat (market, 'tickSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const status = this.safeString (market, 'status'); const active = (status === 'TRADING'); @@ -283,14 +285,14 @@ module.exports = class currencycom extends Exchange { 'max': undefined, }, 'cost': { - 'min': -1 * Math.log10 (precision['amount']), + 'min': -Math.log10 (precision['amount']), 'max': undefined, }, }, }; - const exchangeFee = this.safeFloat2 (market, 'exchangeFee', 'tradingFee'); - const makerFee = this.safeFloat (market, 'makerFee', exchangeFee); - const takerFee = this.safeFloat (market, 'takerFee', exchangeFee); + const exchangeFee = this.safeNumber2 (market, 'exchangeFee', 'tradingFee'); + const makerFee = this.safeNumber (market, 'makerFee', exchangeFee); + const takerFee = this.safeNumber (market, 'takerFee', exchangeFee); if (makerFee !== undefined) { entry['maker'] = makerFee / 100; } @@ -299,65 +301,44 @@ module.exports = class currencycom extends Exchange { } if ('PRICE_FILTER' in filtersByType) { const filter = this.safeValue (filtersByType, 'PRICE_FILTER', {}); - entry['precision']['price'] = this.safeFloat (filter, 'tickSize'); + entry['precision']['price'] = this.safeNumber (filter, 'tickSize'); // PRICE_FILTER reports zero values for maxPrice // since they updated filter types in November 2018 // https://github.com/ccxt/ccxt/issues/4286 // therefore limits['price']['max'] doesn't have any meaningful value except undefined entry['limits']['price'] = { - 'min': this.safeFloat (filter, 'minPrice'), + 'min': this.safeNumber (filter, 'minPrice'), 'max': undefined, }; - const maxPrice = this.safeFloat (filter, 'maxPrice'); + const maxPrice = this.safeNumber (filter, 'maxPrice'); if ((maxPrice !== undefined) && (maxPrice > 0)) { entry['limits']['price']['max'] = maxPrice; } } if ('LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'LOT_SIZE', {}); - entry['precision']['amount'] = this.safeFloat (filter, 'stepSize'); + entry['precision']['amount'] = this.safeNumber (filter, 'stepSize'); entry['limits']['amount'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MARKET_LOT_SIZE' in filtersByType) { const filter = this.safeValue (filtersByType, 'MARKET_LOT_SIZE', {}); entry['limits']['market'] = { - 'min': this.safeFloat (filter, 'minQty'), - 'max': this.safeFloat (filter, 'maxQty'), + 'min': this.safeNumber (filter, 'minQty'), + 'max': this.safeNumber (filter, 'maxQty'), }; } if ('MIN_NOTIONAL' in filtersByType) { const filter = this.safeValue (filtersByType, 'MIN_NOTIONAL', {}); - entry['limits']['cost']['min'] = this.safeFloat (filter, 'minNotional'); + entry['limits']['cost']['min'] = this.safeNumber (filter, 'minNotional'); } result.push (entry); } return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchAccounts (params = {}) { const response = await this.privateGetAccount (params); // @@ -404,8 +385,8 @@ module.exports = class currencycom extends Exchange { const response = await this.privateGetAccount (params); return { 'info': response, - 'maker': this.safeFloat (response, 'makerCommission'), - 'taker': this.safeFloat (response, 'takerCommission'), + 'maker': this.safeNumber (response, 'makerCommission'), + 'taker': this.safeNumber (response, 'takerCommission'), }; } @@ -439,11 +420,11 @@ module.exports = class currencycom extends Exchange { const currencyId = this.safeString (balance, 'asset'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -542,8 +523,8 @@ module.exports = class currencycom extends Exchange { const timestamp = this.safeInteger (ticker, 'closeTime'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPrice'); - const open = this.safeFloat (ticker, 'openPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); let average = undefined; if ((open !== undefined) && (last !== undefined)) { average = this.sum (open, last) / 2; @@ -552,22 +533,22 @@ module.exports = class currencycom extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat (ticker, 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat (ticker, 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), - 'vwap': this.safeFloat (ticker, 'weightedAvgPrice'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber (ticker, 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber (ticker, 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), + 'vwap': this.safeNumber (ticker, 'weightedAvgPrice'), 'open': open, 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'prevClosePrice'), // previous day close - 'change': this.safeFloat (ticker, 'priceChange'), - 'percentage': this.safeFloat (ticker, 'priceChangePercent'), + 'previousClose': this.safeNumber (ticker, 'prevClosePrice'), // previous day close + 'change': this.safeNumber (ticker, 'priceChange'), + 'percentage': this.safeNumber (ticker, 'priceChangePercent'), 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume'), 'info': ticker, }; } @@ -602,14 +583,6 @@ module.exports = class currencycom extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker24hr (params); @@ -642,11 +615,11 @@ module.exports = class currencycom extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -712,8 +685,11 @@ module.exports = class currencycom extends Exchange { // } // const timestamp = this.safeInteger2 (trade, 'T', 'time'); - const price = this.safeFloat2 (trade, 'p', 'price'); - const amount = this.safeFloat2 (trade, 'q', 'qty'); + const priceString = this.safeString2 (trade, 'p', 'price'); + const amountString = this.safeString2 (trade, 'q', 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString2 (trade, 'a', 'id'); let side = undefined; const orderId = this.safeString (trade, 'orderId'); @@ -729,7 +705,7 @@ module.exports = class currencycom extends Exchange { let fee = undefined; if ('commission' in trade) { fee = { - 'cost': this.safeFloat (trade, 'commission'), + 'cost': this.safeNumber (trade, 'commission'), 'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAsset')), }; } @@ -751,7 +727,7 @@ module.exports = class currencycom extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': price * amount, + 'cost': cost, 'fee': fee, }; } @@ -827,66 +803,21 @@ module.exports = class currencycom extends Exchange { } else if ('transactTime' in order) { timestamp = this.safeInteger (order, 'transactTime'); } - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'origQty'); - const filled = this.safeFloat (order, 'executedQty'); - let remaining = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - if (this.options['parseOrderToPrecision']) { - remaining = parseFloat (this.amountToPrecision (symbol, remaining)); - } - remaining = Math.max (remaining, 0.0); - } - if (price !== undefined) { - if (cost === undefined) { - cost = price * filled; - } - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'origQty'); + const filled = this.safeNumber (order, 'executedQty'); + const remaining = undefined; + const cost = this.safeNumber (order, 'cummulativeQuoteQty'); const id = this.safeString (order, 'orderId'); const type = this.safeStringLower (order, 'type'); - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const side = this.safeStringLower (order, 'side'); - let fee = undefined; let trades = undefined; const fills = this.safeValue (order, 'fills'); if (fills !== undefined) { trades = this.parseTrades (fills, market); - const numTrades = trades.length; - if (numTrades > 0) { - cost = trades[0]['cost']; - fee = { - 'cost': trades[0]['fee']['cost'], - 'currency': trades[0]['fee']['currency'], - }; - for (let i = 1; i < trades.length; i++) { - cost = this.sum (cost, trades[i]['cost']); - fee['cost'] = this.sum (fee['cost'], trades[i]['fee']['cost']); - } - } - } - let average = undefined; - if (cost !== undefined) { - if (filled) { - average = cost / filled; - } - if (this.options['parseOrderToPrecision']) { - cost = parseFloat (this.costToPrecision (symbol, cost)); - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'timestamp': timestamp, @@ -900,13 +831,13 @@ module.exports = class currencycom extends Exchange { 'stopPrice': undefined, 'amount': amount, 'cost': cost, - 'average': average, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/delta.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/delta.js index 9b3c559bf..028cdf3ac 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/delta.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/delta.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, BadRequest, BadSymbol, InvalidOrder, AuthenticationError, ArgumentsRequired, OrderNotFound, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -258,14 +259,14 @@ module.exports = class delta extends Exchange { 'name': this.safeString (currency, 'name'), 'info': currency, // the original payload 'active': active, - 'fee': this.safeFloat (currency, 'base_withdrawal_fee'), + 'fee': this.safeNumber (currency, 'base_withdrawal_fee'), 'precision': 1 / Math.pow (10, precision), 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal_amount'), + 'min': this.safeNumber (currency, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -399,26 +400,26 @@ module.exports = class delta extends Exchange { } const precision = { 'amount': 1.0, // number of contracts - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; const limits = { 'amount': { 'min': 1.0, - 'max': this.safeFloat (market, 'position_size_limit'), + 'max': this.safeNumber (market, 'position_size_limit'), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_size'), + 'min': this.safeNumber (market, 'min_size'), 'max': undefined, }, }; const state = this.safeString (market, 'state'); const active = (state === 'live'); - const maker = this.safeFloat (market, 'maker_commission_rate'); - const taker = this.safeFloat (market, 'taker_commission_rate'); + const maker = this.safeNumber (market, 'maker_commission_rate'); + const taker = this.safeNumber (market, 'taker_commission_rate'); result.push ({ 'id': id, 'numericId': numericId, @@ -466,8 +467,8 @@ module.exports = class delta extends Exchange { const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.001); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'close'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; let percentage = undefined; @@ -478,15 +479,15 @@ module.exports = class delta extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'turnover'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'turnover'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -656,12 +657,11 @@ module.exports = class delta extends Exchange { const orderId = this.safeString (trade, 'order_id'); let timestamp = this.parse8601 (this.safeString (trade, 'created_at')); timestamp = this.safeIntegerProduct (trade, 'timestamp', 0.001, timestamp); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const product = this.safeValue (trade, 'product', {}); const marketId = this.safeString (product, 'symbol'); const symbol = this.safeSymbol (marketId, market); @@ -680,7 +680,7 @@ module.exports = class delta extends Exchange { if (type !== undefined) { type = type.replace ('_order', ''); } - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { const settlingAsset = this.safeValue (product, 'settling_asset', {}); @@ -747,11 +747,11 @@ module.exports = class delta extends Exchange { // return [ this.safeTimestamp (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -821,11 +821,11 @@ module.exports = class delta extends Exchange { const currency = this.safeValue (currenciesByNumericId, currencyId); const code = (currency === undefined) ? currencyId : currency['code']; const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchPosition (symbol, params = undefined) { @@ -849,7 +849,7 @@ module.exports = class delta extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetPositionsMargined (params); // @@ -930,20 +930,12 @@ module.exports = class delta extends Exchange { const side = this.safeString (order, 'side'); let type = this.safeString (order, 'order_type'); type = type.replace ('_order', ''); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'size'); - const remaining = this.safeFloat (order, 'unfilled_size'); - let filled = undefined; - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let cost = undefined; - const average = this.safeFloat (order, 'average_fill_price'); - if ((average !== undefined) && filled) { - cost = average * filled; - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'size'); + const remaining = this.safeNumber (order, 'unfilled_size'); + const average = this.safeNumber (order, 'average_fill_price'); let fee = undefined; - const feeCost = this.safeFloat (order, 'paid_commission'); + const feeCost = this.safeNumber (order, 'paid_commission'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -956,7 +948,7 @@ module.exports = class delta extends Exchange { 'currency': feeCurrencyCode, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -968,14 +960,14 @@ module.exports = class delta extends Exchange { 'side': side, 'price': price, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1374,9 +1366,9 @@ module.exports = class delta extends Exchange { const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId'); currency = this.safeValue (currenciesByNumericId, currencyId, currency); const code = (currency === undefined) ? undefined : currency['code']; - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'created_at')); - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const before = Math.max (0, after - amount); const status = 'ok'; return { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/deribit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/deribit.js index f277c3975..1a7c91bec 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/deribit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/deribit.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, DDoSProtection, NotSupported, ExchangeNotAvailable, InsufficientFunds, BadRequest, InvalidAddress, OnMaintenance } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -435,8 +436,8 @@ module.exports = class deribit extends Exchange { const future = (type === 'future'); const option = (type === 'option'); const active = this.safeValue (market, 'is_active'); - const minTradeAmount = this.safeFloat (market, 'min_trade_amount'); - const tickSize = this.safeFloat (market, 'tick_size'); + const minTradeAmount = this.safeNumber (market, 'min_trade_amount'); + const tickSize = this.safeNumber (market, 'tick_size'); const precision = { 'amount': minTradeAmount, 'price': tickSize, @@ -448,8 +449,8 @@ module.exports = class deribit extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_commission'), - 'maker': this.safeFloat (market, 'maker_commission'), + 'taker': this.safeNumber (market, 'taker_commission'), + 'maker': this.safeNumber (market, 'maker_commission'), 'limits': { 'amount': { 'min': minTradeAmount, @@ -532,11 +533,11 @@ module.exports = class deribit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const currencyCode = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableFunds'); - account['used'] = this.safeFloat (balance, 'maintenanceMargin'); - account['total'] = this.safeFloat (balance, 'equity'); + account['free'] = this.safeString (balance, 'availableFunds'); + account['used'] = this.safeString (balance, 'maintenanceMargin'); + account['total'] = this.safeString (balance, 'equity'); result[currencyCode] = account; - return this.parseBalance (result); + return this.parseBalance (result, false); } async createDepositAddress (code, params = {}) { @@ -654,18 +655,18 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger2 (ticker, 'timestamp', 'creation_timestamp'); const marketId = this.safeString (ticker, 'instrument_name'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat2 (ticker, 'last_price', 'last'); + const last = this.safeNumber2 (ticker, 'last_price', 'last'); const stats = this.safeValue (ticker, 'stats', ticker); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (stats, 'high', 'max_price'), - 'low': this.safeFloat2 (stats, 'low', 'min_price'), - 'bid': this.safeFloat2 (ticker, 'best_bid_price', 'bid_price'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_amount'), - 'ask': this.safeFloat2 (ticker, 'best_ask_price', 'ask_price'), - 'askVolume': this.safeFloat (ticker, 'best_ask_amount'), + 'high': this.safeNumber2 (stats, 'high', 'max_price'), + 'low': this.safeNumber2 (stats, 'low', 'min_price'), + 'bid': this.safeNumber2 (ticker, 'best_bid_price', 'bid_price'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_amount'), + 'ask': this.safeNumber2 (ticker, 'best_ask_price', 'ask_price'), + 'askVolume': this.safeNumber (ticker, 'best_ask_amount'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -675,7 +676,7 @@ module.exports = class deribit extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (stats, 'volume'), + 'quoteVolume': this.safeNumber (stats, 'volume'), 'info': ticker, }; } @@ -862,21 +863,18 @@ module.exports = class deribit extends Exchange { const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeString (trade, 'direction'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const liquidity = this.safeString (trade, 'liquidity'); let takerOrMaker = undefined; if (liquidity !== undefined) { // M = maker, T = taker, MT = both takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker'; } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -1056,31 +1054,21 @@ module.exports = class deribit extends Exchange { const timestamp = this.safeInteger (order, 'creation_timestamp'); const lastUpdate = this.safeInteger (order, 'last_update_timestamp'); const id = this.safeString (order, 'order_id'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'average_price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'average_price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); let lastTradeTimestamp = undefined; if (filled !== undefined) { if (filled > 0) { lastTradeTimestamp = lastUpdate; } } - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = price * filled; - } - } const status = this.parseOrderStatus (this.safeString (order, 'order_state')); const marketId = this.safeString (order, 'instrument_name'); market = this.safeMarket (marketId, market); const side = this.safeStringLower (order, 'direction'); - let feeCost = this.safeFloat (order, 'commission'); + let feeCost = this.safeNumber (order, 'commission'); let fee = undefined; if (feeCost !== undefined) { feeCost = Math.abs (feeCost); @@ -1098,7 +1086,7 @@ module.exports = class deribit extends Exchange { const timeInForce = this.parseTimeInForce (this.safeString (order, 'time_in_force')); const stopPrice = this.safeValue (order, 'stop_price'); const postOnly = this.safeValue (order, 'post_only'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1113,14 +1101,14 @@ module.exports = class deribit extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1197,7 +1185,7 @@ module.exports = class deribit extends Exchange { } } if (stopPriceIsRequired) { - const stopPrice = this.safeFloat2 (params, 'stop_price', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price or stopPrice param for a ' + type + ' order'); } else { @@ -1596,7 +1584,7 @@ module.exports = class deribit extends Exchange { const updated = this.safeInteger (transaction, 'updated_timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const address = this.safeString (transaction, 'address'); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let type = 'deposit'; let fee = undefined; if (feeCost !== undefined) { @@ -1619,7 +1607,7 @@ module.exports = class deribit extends Exchange { 'tagTo': undefined, 'tagFrom': undefined, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, @@ -1665,7 +1653,7 @@ module.exports = class deribit extends Exchange { return result; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.codeFromOptions ('fetchPositions'); const currency = this.currency (code); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/digifinex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/digifinex.js index 6584b919c..528126688 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/digifinex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/digifinex.js @@ -3,7 +3,8 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); -const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ArgumentsRequired, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const { AccountSuspended, BadRequest, BadResponse, NetworkError, DDoSProtection, AuthenticationError, PermissionDenied, ExchangeError, InsufficientFunds, InvalidOrder, InvalidNonce, OrderNotFound, InvalidAddress, RateLimitExceeded, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -61,11 +62,6 @@ module.exports = class digifinex extends Exchange { 'referral': 'https://www.digifinex.com/en-ww/from/DhOzBg?channelCode=ljaUPp', }, 'api': { - 'v2': { - 'get': [ - 'ticker', - ], - }, 'public': { 'get': [ '{market}/symbols', @@ -191,6 +187,7 @@ module.exports = class digifinex extends Exchange { }, 'commonCurrencies': { 'BHT': 'Black House Test', + 'EPS': 'Epanus', 'MBN': 'Mobilian Coin', 'TEL': 'TEL666', }, @@ -245,7 +242,7 @@ module.exports = class digifinex extends Exchange { const depositStatus = this.safeValue (currency, 'deposit_status', 1); const withdrawStatus = this.safeValue (currency, 'withdraw_status', 1); const active = depositStatus && withdrawStatus; - const fee = this.safeFloat (currency, 'withdraw_fee_rate'); + const fee = this.safeNumber (currency, 'withdraw_fee_rate'); if (code in result) { if (Array.isArray (result[code]['info'])) { result[code]['info'].push (currency); @@ -276,7 +273,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw_amount'), + 'min': this.safeNumber (currency, 'min_withdraw_amount'), 'max': undefined, }, }, @@ -330,7 +327,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minimum_amount'), + 'min': this.safeNumber (market, 'minimum_amount'), 'max': undefined, }, 'price': { @@ -338,7 +335,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minimum_value'), + 'min': this.safeNumber (market, 'minimum_value'), 'max': undefined, }, }; @@ -352,7 +349,7 @@ module.exports = class digifinex extends Exchange { // const status = this.safeString (market, 'status'); // const active = (status === 'TRADING'); // - const isAllowed = this.safeValue (market, 'is_allow', 1); + const isAllowed = this.safeInteger (market, 'is_allow', 1); const active = isAllowed ? true : false; const type = 'spot'; const spot = (type === 'spot'); @@ -408,7 +405,7 @@ module.exports = class digifinex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), + 'min': this.safeNumber (market, 'min_volume'), 'max': undefined, }, 'price': { @@ -416,7 +413,7 @@ module.exports = class digifinex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, }; @@ -461,12 +458,12 @@ module.exports = class digifinex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['used'] = this.safeFloat (balance, 'frozen'); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['used'] = this.safeString (balance, 'frozen'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -500,87 +497,67 @@ module.exports = class digifinex extends Exchange { } async fetchTickers (symbols = undefined, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTickers() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); - const request = { - 'apiKey': apiKey, - }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (params); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const result = {}; - const tickers = this.safeValue (response, 'ticker', {}); + const tickers = this.safeValue (response, 'ticker', []); const date = this.safeInteger (response, 'date'); - const reversedMarketIds = Object.keys (tickers); - for (let i = 0; i < reversedMarketIds.length; i++) { - const reversedMarketId = reversedMarketIds[i]; - const ticker = this.extend ({ + for (let i = 0; i < tickers.length; i++) { + const rawTicker = this.extend ({ 'date': date, - }, tickers[reversedMarketId]); - const [ quoteId, baseId ] = reversedMarketId.split ('_'); - const marketId = baseId.toUpperCase () + '_' + quoteId.toUpperCase (); - const market = this.safeMarket (marketId, undefined, '_'); - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); + }, tickers[i]); + const ticker = this.parseTicker (rawTicker); + const symbol = ticker['symbol']; + result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTicker (symbol, params = {}) { - const apiKey = this.safeValue (params, 'apiKey', this.apiKey); - if (!apiKey) { - throw new ArgumentsRequired (this.id + ' fetchTicker() is a private v2 endpoint that requires an `exchange.apiKey` credential or an `apiKey` extra parameter'); - } await this.loadMarkets (); const market = this.market (symbol); - // reversed base/quote in v2 - const marketId = market['quoteId'].toLowerCase () + '_' + market['baseId'].toLowerCase (); const request = { - 'symbol': marketId, - 'apiKey': apiKey, + 'symbol': market['id'], }; - const response = await this.v2GetTicker (this.extend (request, params)); + const response = await this.publicGetTicker (this.extend (request, params)); // - // { - // "ticker":{ - // "btc_eth":{ - // "last":0.021957, - // "base_vol":2249.3521732227, - // "change":-0.6, - // "vol":102443.5111, - // "sell":0.021978, - // "low":0.021791, - // "buy":0.021946, - // "high":0.022266 - // } - // }, - // "date":1564518452, - // "code":0 - // } + // { + // "ticker": [{ + // "vol": 40717.4461, + // "change": -1.91, + // "base_vol": 392447999.65374, + // "sell": 9592.23, + // "last": 9592.22, + // "symbol": "btc_usdt", + // "low": 9476.24, + // "buy": 9592.03, + // "high": 9793.87 + // }], + // "date": 1589874294, + // "code": 0 + // } // const date = this.safeInteger (response, 'date'); - const ticker = this.safeValue (response, 'ticker', {}); - let result = this.safeValue (ticker, marketId, {}); - result = this.extend ({ 'date': date }, result); + const tickers = this.safeValue (response, 'ticker', []); + const firstTicker = this.safeValue (tickers, 0, {}); + const result = this.extend ({ 'date': date }, firstTicker); return this.parseTicker (result, market); } @@ -590,6 +567,7 @@ module.exports = class digifinex extends Exchange { // // { // "last":0.021957, + // "symbol": "btc_usdt", // "base_vol":2249.3521732227, // "change":-0.6, // "vol":102443.5111, @@ -600,22 +578,20 @@ module.exports = class digifinex extends Exchange { // "date"1564518452, // injected from fetchTicker/fetchTickers // } // - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeStringUpper (ticker, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -625,8 +601,8 @@ module.exports = class digifinex extends Exchange { 'change': undefined, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'base_vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'base_vol'), 'info': ticker, }; } @@ -662,18 +638,15 @@ module.exports = class digifinex extends Exchange { const orderId = this.safeString (trade, 'order_id'); const timestamp = this.safeTimestamp2 (trade, 'date', 'timestamp'); const side = this.safeString2 (trade, 'type', 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); const takerOrMaker = this.safeValue (trade, 'is_maker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency'); @@ -775,11 +748,11 @@ module.exports = class digifinex extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 5), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 1), // volume + this.safeNumber (ohlcv, 5), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 1), // volume ]; } @@ -970,21 +943,11 @@ module.exports = class digifinex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executed_amount'); - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_price'); - let remaining = undefined; - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - return { + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executed_amount'); + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1000,13 +963,13 @@ module.exports = class digifinex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'average': average, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1200,7 +1163,7 @@ module.exports = class digifinex extends Exchange { const code = this.safeCurrencyCode (this.safeString (item, 'currency_mark'), currency); const timestamp = this.safeTimestamp (item, 'time'); const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -1263,16 +1226,6 @@ module.exports = class digifinex extends Exchange { return this.parseLedger (items, currency, since, limit); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -1425,8 +1378,8 @@ module.exports = class digifinex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_date')); const updated = this.parse8601 (this.safeString (transaction, 'finished_date')); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'amount'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; @@ -1476,7 +1429,7 @@ module.exports = class digifinex extends Exchange { } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const version = (api === 'v2') ? api : this.version; + const version = this.version; let url = this.urls['api'] + '/' + version + '/' + this.implodeParams (path, params); const query = this.omit (params, this.extractParams (path)); const urlencoded = this.urlencode (this.keysort (query)); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/dsx.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/dsx.js deleted file mode 100644 index 349fc2489..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/dsx.js +++ /dev/null @@ -1,1274 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, BadRequest, InsufficientFunds, PermissionDenied, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class dsx extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'dsx', - 'name': 'DSX', - 'countries': [ 'UK' ], - 'rateLimit': 1500, - 'version': 'v3', - 'has': { - 'cancelOrder': true, - 'CORS': false, - 'createDepositAddress': true, - 'createMarketOrder': false, - 'createOrder': true, - 'fetchBalance': true, - 'fetchClosedOrders': false, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOHLCV': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchOrderBooks': true, - 'fetchOrders': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTransactions': true, - 'fetchTrades': true, - 'withdraw': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/76909626-cb2bb100-68bc-11ea-99e0-28ba54f04792.jpg', - 'api': { - 'public': 'https://dsxglobal.com/mapi', // market data - 'private': 'https://dsxglobal.com/tapi', // trading - 'dwapi': 'https://dsxglobal.com/dwapi', // deposit/withdraw - }, - 'www': 'https://dsxglobal.com', - 'doc': [ - 'https://dsxglobal.com/developers/publicApi', - ], - }, - 'fees': { - 'trading': { - 'tierBased': true, - 'percentage': true, - 'maker': 0.15 / 100, - 'taker': 0.25 / 100, - }, - }, - 'timeframes': { - '1m': 'm', - '1h': 'h', - '1d': 'd', - }, - 'api': { - // market data (public) - 'public': { - 'get': [ - 'barsFromMoment/{pair}/{period}/{start}', - 'depth/{pair}', - 'info', - 'lastBars/{pair}/{period}/{amount}', // period is 'm', 'h' or 'd' - 'periodBars/{pair}/{period}/{start}/{end}', - 'ticker/{pair}', - 'trades/{pair}', - ], - }, - // trading (private) - 'private': { - 'post': [ - 'info/account', - 'history/transactions', - 'history/trades', - 'history/orders', - 'orders', - 'order/cancel', - // 'order/cancel/all', - 'order/status', - 'order/new', - 'volume', - 'fees', // trading fee schedule - ], - }, - // deposit / withdraw (private) - 'dwapi': { - 'post': [ - 'deposit/cryptoaddress', - 'withdraw/crypto', - 'withdraw/fiat', - 'withdraw/submit', - // 'withdraw/cancel', - 'transaction/status', // see 'history/transactions' in private tapi above - ], - }, - }, - 'exceptions': { - 'exact': { - 'Sign is invalid': AuthenticationError, // {"success":0,"error":"Sign is invalid"} - 'Order was rejected. Incorrect price.': InvalidOrder, // {"success":0,"error":"Order was rejected. Incorrect price."} - "Order was rejected. You don't have enough money.": InsufficientFunds, // {"success":0,"error":"Order was rejected. You don't have enough money."} - 'This method is blocked for your pair of keys': PermissionDenied, // {"success":0,"error":"This method is blocked for your pair of keys"} - }, - 'broad': { - 'INVALID_PARAMETER': BadRequest, - 'Invalid pair name': ExchangeError, // {"success":0,"error":"Invalid pair name: btc_eth"} - 'invalid api key': AuthenticationError, - 'invalid sign': AuthenticationError, - 'api key dont have trade permission': AuthenticationError, - 'invalid parameter': InvalidOrder, - 'invalid order': InvalidOrder, - 'Requests too often': DDoSProtection, - 'not available': ExchangeNotAvailable, - 'data unavailable': ExchangeNotAvailable, - 'external service unavailable': ExchangeNotAvailable, - 'nonce is invalid': InvalidNonce, // {"success":0,"error":"Parameter: nonce is invalid"} - 'Incorrect volume': InvalidOrder, // {"success": 0,"error":"Order was rejected. Incorrect volume."} - }, - }, - 'options': { - 'fetchTickersMaxLength': 250, - }, - 'commonCurrencies': { - 'DSH': 'DASH', - }, - }); - } - - async fetchMarkets (params = {}) { - const response = await this.publicGetInfo (params); - // - // { - // "server_time": 1522057909, - // "pairs": { - // "ethusd": { - // "decimal_places": 5, - // "min_price": 100, - // "max_price": 1500, - // "min_amount": 0.01, - // "hidden": 0, - // "fee": 0, - // "amount_decimal_places": 4, - // "quoted_currency": "USD", - // "base_currency": "ETH" - // } - // } - // } - // - const markets = this.safeValue (response, 'pairs'); - const keys = Object.keys (markets); - const result = []; - for (let i = 0; i < keys.length; i++) { - const id = keys[i]; - const market = markets[id]; - const baseId = this.safeString (market, 'base_currency'); - const quoteId = this.safeString (market, 'quoted_currency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const precision = { - 'amount': this.safeInteger (market, 'decimal_places'), - 'price': this.safeInteger (market, 'decimal_places'), - }; - const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), - }; - const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), - }; - const costLimits = { - 'min': this.safeFloat (market, 'min_total'), - }; - const limits = { - 'amount': amountLimits, - 'price': priceLimits, - 'cost': costLimits, - }; - const hidden = this.safeInteger (market, 'hidden'); - const active = (hidden === 0); - // see parseMarket below - // https://github.com/ccxt/ccxt/pull/5786 - const otherId = base.toLowerCase () + quote.toLowerCase (); - result.push ({ - 'id': id, - 'otherId': otherId, // https://github.com/ccxt/ccxt/pull/5786 - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': active, - 'precision': precision, - 'limits': limits, - 'info': market, - }); - } - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostInfoAccount (); - // - // { - // "success" : 1, - // "return" : { - // "funds" : { - // "BTC" : { - // "total" : 0, - // "available" : 0 - // }, - // "USD" : { - // "total" : 0, - // "available" : 0 - // }, - // "USDT" : { - // "total" : 0, - // "available" : 0 - // } - // }, - // "rights" : { - // "info" : 1, - // "trade" : 1 - // }, - // "transactionCount" : 0, - // "openOrders" : 0, - // "serverTime" : 1537451465 - // } - // } - // - const balances = this.safeValue (response, 'return'); - const result = { 'info': response }; - const funds = this.safeValue (balances, 'funds'); - const currencyIds = Object.keys (funds); - for (let i = 0; i < currencyIds.length; i++) { - const currencyId = currencyIds[i]; - const code = this.safeCurrencyCode (currencyId); - const balance = this.safeValue (funds, currencyId, {}); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseTicker (ticker, market = undefined) { - // - // { high: 0.03492, - // low: 0.03245, - // avg: 29.46133, - // vol: 500.8661, - // vol_cur: 17.000797104, - // last: 0.03364, - // buy: 0.03362, - // sell: 0.03381, - // updated: 1537521993, - // pair: "ethbtc" } - // - const timestamp = this.safeTimestamp (ticker, 'updated'); - let symbol = undefined; - const marketId = this.safeString (ticker, 'pair'); - market = this.parseMarket (marketId); - if (market !== undefined) { - symbol = market['symbol']; - } - // dsx average is inverted, liqui average is not - let average = this.safeFloat (ticker, 'avg'); - if (average !== undefined) { - if (average > 0) { - average = 1 / average; - } - } - const last = this.safeFloat (ticker, 'last'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_cur'), - 'info': ticker, - }; - } - - parseTrade (trade, market = undefined) { - // - // fetchTrades (public) - // - // { - // "amount" : 0.0128, - // "price" : 6483.99000, - // "timestamp" : 1540334614, - // "tid" : 35684364, - // "type" : "ask" - // } - // - // fetchMyTrades (private) - // - // { - // "number": "36635882", // <-- this is present if the trade has come from the '/order/status' call - // "id": "36635882", // <-- this may have been artifically added by the parseTrades method - // "pair": "btcusd", - // "type": "buy", - // "volume": 0.0595, - // "rate": 9750, - // "orderId": 77149299, - // "timestamp": 1519612317, - // "commission": 0.00020825, - // "commissionCurrency": "btc" - // } - // - const timestamp = this.safeTimestamp (trade, 'timestamp'); - let side = this.safeString (trade, 'type'); - if (side === 'ask') { - side = 'sell'; - } else if (side === 'bid') { - side = 'buy'; - } - const price = this.safeFloat2 (trade, 'rate', 'price'); - const id = this.safeString2 (trade, 'number', 'id'); - const orderId = this.safeString (trade, 'orderId'); - const marketId = this.safeString (trade, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const amount = this.safeFloat2 (trade, 'amount', 'volume'); - const type = 'limit'; // all trades are still limit trades - let takerOrMaker = undefined; - let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); - if (feeCost !== undefined) { - const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); - const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - fee = { - 'cost': feeCost, - 'currency': feeCurrencyCode, - }; - } - const isYourOrder = this.safeValue (trade, 'is_your_order'); - if (isYourOrder !== undefined) { - takerOrMaker = 'taker'; - if (isYourOrder) { - takerOrMaker = 'maker'; - } - if (fee === undefined) { - fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); - } - } - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - return { - 'id': id, - 'order': orderId, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'type': type, - 'side': side, - 'takerOrMaker': takerOrMaker, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - 'info': trade, - }; - } - - parseTrades (trades, market = undefined, since = undefined, limit = undefined, params = {}) { - let result = []; - if (Array.isArray (trades)) { - for (let i = 0; i < trades.length; i++) { - result.push (this.parseTrade (trades[i], market)); - } - } else { - const ids = Object.keys (trades); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const trade = this.parseTrade (trades[id], market); - result.push (this.extend (trade, { 'id': id }, params)); - } - } - result = this.sortBy (result, 'timestamp'); - const symbol = (market !== undefined) ? market['symbol'] : undefined; - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const market_id_in_reponse = (market['id'] in response); - if (!market_id_in_reponse) { - throw new ExchangeError (this.id + ' ' + market['symbol'] + ' order book is empty or not available'); - } - const orderbook = response[market['id']]; - return this.parseOrderBook (orderbook); - } - - async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let ids = undefined; - if (symbols === undefined) { - ids = this.ids.join ('-'); - // max URL length is 2083 symbols, including http schema, hostname, tld, etc... - if (ids.length > 2048) { - const numIds = this.ids.length; - throw new ExchangeError (this.id + ' has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - if (limit !== undefined) { - request['limit'] = limit; // default = 150, max = 2000 - } - const response = await this.publicGetDepthPair (this.extend (request, params)); - const result = {}; - ids = Object.keys (response); - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - let symbol = id; - if (id in this.markets_by_id) { - const market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseOrderBook (response[id]); - } - return result; - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - let ids = this.ids; - if (symbols === undefined) { - const numIds = ids.length; - ids = ids.join ('-'); - const maxLength = this.safeInteger (this.options, 'fetchTickersMaxLength', 2048); - // max URL length is 2048 symbols, including http schema, hostname, tld, etc... - if (ids.length > this.options['fetchTickersMaxLength']) { - throw new ArgumentsRequired (this.id + ' has ' + numIds.toString () + ' markets exceeding max URL length for this endpoint (' + maxLength.toString () + ' characters), please, specify a list of symbols of interest in the first argument to fetchTickers'); - } - } else { - ids = this.marketIds (symbols); - ids = ids.join ('-'); - } - const request = { - 'pair': ids, - }; - const tickers = await this.publicGetTickerPair (this.extend (request, params)); - // - // { - // "bchbtc" : { - // "high" : 0.02989, - // "low" : 0.02736, - // "avg" : 33.90585, - // "vol" : 0.65982205, - // "vol_cur" : 0.0194604180960, - // "last" : 0.03000, - // "buy" : 0.02980, - // "sell" : 0.03001, - // "updated" : 1568104614, - // "pair" : "bchbtc" - // }, - // "ethbtc" : { - // "high" : 0.01772, - // "low" : 0.01742, - // "avg" : 56.89082, - // "vol" : 229.247115044, - // "vol_cur" : 4.02959737298943, - // "last" : 0.01769, - // "buy" : 0.01768, - // "sell" : 0.01776, - // "updated" : 1568104614, - // "pair" : "ethbtc" - // } - // } - // - const result = {}; - const keys = Object.keys (tickers); - for (let k = 0; k < keys.length; k++) { - const id = keys[k]; - const ticker = tickers[id]; - let symbol = id; - let market = undefined; - if (id in this.markets_by_id) { - market = this.markets_by_id[id]; - symbol = market['symbol']; - } - result[symbol] = this.parseTicker (ticker, market); - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchTicker (symbol, params = {}) { - const tickers = await this.fetchTickers ([ symbol ], params); - return tickers[symbol]; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - }; - if (limit !== undefined) { - request['limit'] = limit; - } - const response = await this.publicGetTradesPair (this.extend (request, params)); - if (Array.isArray (response)) { - const numElements = response.length; - if (numElements === 0) { - return []; - } - } - return this.parseTrades (response[market['id']], market, since, limit); - } - - parseOHLCV (ohlcv, market = undefined) { - // - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // } - // - return [ - this.safeInteger (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), - ]; - } - - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair': market['id'], - 'period': this.timeframes[timeframe], - }; - let method = 'publicGetLastBarsPairPeriodAmount'; - if (since === undefined) { - if (limit === undefined) { - limit = 100; // required, max 2000 - } - request['amount'] = limit; - } else { - method = 'publicGetPeriodBarsPairPeriodStartEnd'; - // in their docs they expect milliseconds - // but it returns empty arrays with milliseconds - // however, it does work properly with seconds - request['start'] = parseInt (since / 1000); - if (limit === undefined) { - request['end'] = this.seconds (); - } else { - const duration = this.parseTimeframe (timeframe) * 1000; - const end = this.sum (since, duration * limit); - request['end'] = parseInt (end / 1000); - } - } - const response = await this[method] (this.extend (request, params)); - // - // { - // "ethbtc": [ - // { - // "high" : 0.01955, - // "open" : 0.01955, - // "low" : 0.01955, - // "close" : 0.01955, - // "amount" : 2.5, - // "timestamp" : 1565155740000 - // }, - // { - // "high" : 0.01967, - // "open" : 0.01967, - // "low" : 0.01967, - // "close" : 0.01967, - // "amount" : 0, - // "timestamp" : 1565155680000 - // } - // ] - // } - // - const candles = this.safeValue (response, market['id'], []); - return this.parseOHLCVs (candles, market, timeframe, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - if (type === 'market' && price === undefined) { - throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument even for market orders, that is the worst price that you agree to fill your order for'); - } - const request = { - 'pair': market['id'], - 'type': side, - 'volume': this.amountToPrecision (symbol, amount), - 'rate': this.priceToPrecision (symbol, price), - 'orderType': type, - }; - price = parseFloat (price); - amount = parseFloat (amount); - const response = await this.privatePostOrderNew (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "received": 0, - // "remains": 10, - // "funds": { - // "BTC": { - // "total": 100, - // "available": 95 - // }, - // "USD": { - // "total": 10000, - // "available": 9995 - // }, - // "EUR": { - // "total": 1000, - // "available": 995 - // }, - // "LTC": { - // "total": 1000, - // "available": 995 - // } - // }, - // "orderId": 0, // https://github.com/ccxt/ccxt/issues/3677 - // } - // } - // - let status = 'open'; - let filled = 0.0; - let remaining = amount; - const responseReturn = this.safeValue (response, 'return'); - let id = this.safeString2 (responseReturn, 'orderId', 'order_id'); - if (id === '0') { - id = this.safeString (responseReturn, 'initOrderId', 'init_order_id'); - status = 'closed'; - } - filled = this.safeFloat (responseReturn, 'received', 0.0); - remaining = this.safeFloat (responseReturn, 'remains', amount); - const timestamp = this.milliseconds (); - return { - 'info': response, - 'id': id, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': type, - 'side': side, - 'price': price, - 'cost': price * filled, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'fee': undefined, - // 'trades': this.parseTrades (order['trades'], market), - }; - } - - parseOrderStatus (status) { - const statuses = { - '0': 'open', // Active - '1': 'closed', // Filled - '2': 'canceled', // Killed - '3': 'canceling', // Killing - '7': 'canceled', // Rejected - }; - return this.safeString (statuses, status, status); - } - - parseMarket (id) { - if (id in this.markets_by_id) { - return this.markets_by_id[id]; - } else { - // the following is a fix for - // https://github.com/ccxt/ccxt/pull/5786 - // https://github.com/ccxt/ccxt/issues/5770 - let markets_by_other_id = this.safeValue (this.options, 'markets_by_other_id'); - if (markets_by_other_id === undefined) { - this.options['markets_by_other_id'] = this.indexBy (this.markets, 'otherId'); - markets_by_other_id = this.options['markets_by_other_id']; - } - if (id in markets_by_other_id) { - return markets_by_other_id[id]; - } - } - return undefined; - } - - parseOrder (order, market = undefined) { - // - // fetchOrder - // - // { - // "number": 36635882, - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // - const id = this.safeString (order, 'id'); - const status = this.parseOrderStatus (this.safeString (order, 'status')); - const timestamp = this.safeTimestamp (order, 'timestampCreated'); - const marketId = this.safeString (order, 'pair'); - market = this.parseMarket (marketId); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const remaining = this.safeFloat (order, 'remainingVolume'); - const amount = this.safeFloat (order, 'volume'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } - } - const orderType = this.safeString (order, 'orderType'); - const side = this.safeString (order, 'type'); - let fee = undefined; - const deals = this.safeValue (order, 'deals', []); - const numDeals = deals.length; - let trades = undefined; - let lastTradeTimestamp = undefined; - if (numDeals > 0) { - trades = this.parseTrades (deals); - let feeCost = undefined; - let feeCurrency = undefined; - for (let i = 0; i < trades.length; i++) { - const trade = trades[i]; - if (feeCost === undefined) { - feeCost = 0; - } - feeCost = this.sum (feeCost, trade['fee']['cost']); - feeCurrency = trade['fee']['currency']; - lastTradeTimestamp = trade['timestamp']; - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': feeCurrency, - }; - } - } - return { - 'info': order, - 'id': id, - 'clientOrderId': undefined, - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, - 'type': orderType, - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': side, - 'price': price, - 'stopPrice': undefined, - 'cost': cost, - 'amount': amount, - 'remaining': remaining, - 'filled': filled, - 'status': status, - 'fee': fee, - 'trades': trades, - }; - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': parseInt (id), - }; - const response = await this.privatePostOrderStatus (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit", - // "deals": [ - // { - // "pair": "btcusd", - // "type": "buy", - // "amount": 1, - // "rate": 1000.0, - // "orderId": 1, - // "timestamp": 1496672724, - // "commission": 0.001, - // "commissionCurrency": "btc" - // } - // ] - // } - // } - // - return this.parseOrder (this.extend ({ - 'id': id, - }, response['return'])); - } - - parseOrdersById (orders, symbol = undefined, since = undefined, limit = undefined) { - const ids = Object.keys (orders); - const result = []; - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.parseOrder (this.extend ({ - 'id': id.toString (), - }, orders[id])); - result.push (order); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - const response = await this.privatePostOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - // 'count': 10, // Decimal, The maximum number of orders to return - // 'fromId': 123, // Decimal, ID of the first order of the selection - // 'endId': 321, // Decimal, ID of the last order of the selection - // 'order': 'ASC', // String, Order in which orders shown. Possible values are "ASC" — from first to last, "DESC" — from last to first. - }; - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryOrders (this.extend (request, params)); - // - // { - // "success": 1, - // "return": { - // "0": { - // "pair": "btcusd", - // "type": "buy", - // "remainingVolume": 10, - // "volume": 10, - // "rate": 1000.0, - // "timestampCreated": 1496670, - // "status": 0, - // "orderType": "limit" - // } - // } - // } - // - return this.parseOrdersById (this.safeValue (response, 'return', {}), symbol, since, limit); - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'orderId': id, - }; - const response = await this.privatePostOrderCancel (this.extend (request, params)); - return response; - } - - parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) { - const result = []; - const ids = Object.keys (orders); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - for (let i = 0; i < ids.length; i++) { - const id = ids[i]; - const order = this.extend ({ 'id': id }, orders[id]); - result.push (this.extend (this.parseOrder (order, market), params)); - } - return this.filterBySymbolSinceLimit (result, symbol, since, limit); - } - - async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - const orders = await this.fetchOrders (symbol, since, limit, params); - return this.filterBy (orders, 'status', 'closed'); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let market = undefined; - // some derived classes use camelcase notation for request fields - const request = { - // 'from': 123456789, // trade ID, from which the display starts numerical 0 (test result: liqui ignores this field) - // 'count': 1000, // the number of trades for display numerical, default = 1000 - // 'from_id': trade ID, from which the display starts numerical 0 - // 'end_id': trade ID on which the display ends numerical ∞ - // 'order': 'ASC', // sorting, default = DESC (test result: liqui ignores this field, most recent trade always goes last) - // 'since': 1234567890, // UTC start time, default = 0 (test result: liqui ignores this field) - // 'end': 1234567890, // UTC end time, default = ∞ (test result: liqui ignores this field) - // 'pair': 'eth_btc', // default = all markets - }; - if (symbol !== undefined) { - market = this.market (symbol); - request['pair'] = market['id']; - } - if (limit !== undefined) { - request['count'] = parseInt (limit); - } - if (since !== undefined) { - request['since'] = parseInt (since / 1000); - } - const response = await this.privatePostHistoryTrades (this.extend (request, params)); - let trades = []; - if ('return' in response) { - trades = response['return']; - } - return this.parseTrades (trades, market, since, limit); - } - - async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - let currency = undefined; - const request = {}; - if (code !== undefined) { - currency = this.currency (code); - request['currency'] = currency['id']; - } - if (since !== undefined) { - request['since'] = since; - } - if (limit !== undefined) { - request['count'] = limit; - } - const response = await this.privatePostHistoryTransactions (this.extend (request, params)); - // - // { - // "success": 1, - // "return": [ - // { - // "id": 1, - // "timestamp": 11, - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // ] - // } - // - const transactions = this.safeValue (response, 'return', []); - return this.parseTransactions (transactions, currency, since, limit); - } - - parseTransactionStatus (status) { - const statuses = { - '1': 'failed', - '2': 'ok', - '3': 'pending', - '4': 'failed', - }; - return this.safeString (statuses, status, status); - } - - parseTransaction (transaction, currency = undefined) { - // - // { - // "id": 1, - // "timestamp": 11, // 11 in their docs ( - // "type": "Withdraw", - // "amount": 1, - // "currency": "btc", - // "confirmationsCount": 6, - // "address": "address", - // "status": 2, - // "commission": 0.0001 - // } - // - const timestamp = this.safeTimestamp (transaction, 'timestamp'); - let type = this.safeString (transaction, 'type'); - if (type !== undefined) { - if (type === 'Incoming') { - type = 'deposit'; - } else if (type === 'Withdraw') { - type = 'withdrawal'; - } - } - const currencyId = this.safeString (transaction, 'currency'); - const code = this.safeCurrencyCode (currencyId, currency); - const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - return { - 'id': this.safeString (transaction, 'id'), - 'txid': this.safeString (transaction, 'txid'), - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'address': this.safeString (transaction, 'address'), - 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), - 'currency': code, - 'status': status, - 'fee': { - 'currency': code, - 'cost': this.safeFloat (transaction, 'commission'), - 'rate': undefined, - }, - 'info': transaction, - }; - } - - async createDepositAddress (code, params = {}) { - const request = { - 'new': 1, - }; - const response = await this.fetchDepositAddress (code, this.extend (request, params)); - return response; - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency': currency['id'], - }; - const response = await this.dwapiPostDepositCryptoaddress (this.extend (request, params)); - const result = this.safeValue (response, 'return', {}); - const address = this.safeString (result, 'address'); - this.checkAddress (address); - return { - 'currency': code, - 'address': address, - 'tag': undefined, // not documented in DSX API - 'info': response, - }; - } - - async withdraw (code, amount, address, tag = undefined, params = {}) { - this.checkAddress (address); - await this.loadMarkets (); - const currency = this.currency (code); - const commission = this.safeValue (params, 'commission'); - if (commission === undefined) { - throw new ArgumentsRequired (this.id + ' withdraw() requires a `commission` (withdrawal fee) parameter (string)'); - } - params = this.omit (params, commission); - const request = { - 'currency': currency['id'], - 'amount': parseFloat (amount), - 'address': address, - 'commission': commission, - }; - if (tag !== undefined) { - request['address'] += ':' + tag; - } - const response = await this.dwapiPostWithdrawCrypto (this.extend (request, params)); - // - // [ - // { - // "success": 1, - // "return": { - // "transactionId": 2863073 - // } - // } - // ] - // - const data = this.safeValue (response, 'return', {}); - const id = this.safeString (data, 'transactionId'); - return { - 'info': response, - 'id': id, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'][api]; - const query = this.omit (params, this.extractParams (path)); - if (api === 'private' || api === 'dwapi') { - url += '/' + this.version + '/' + this.implodeParams (path, params); - this.checkRequiredCredentials (); - const nonce = this.nonce (); - body = this.urlencode (this.extend ({ - 'nonce': nonce, - }, query)); - const signature = this.hmac (this.encode (body), this.encode (this.secret), 'sha512', 'base64'); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': signature, - }; - } else if (api === 'public') { - url += '/' + this.implodeParams (path, params); - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - url += '/' + this.implodeParams (path, params); - if (method === 'GET') { - if (Object.keys (query).length) { - url += '?' + this.urlencode (query); - } - } else { - if (Object.keys (query).length) { - body = this.json (query); - headers = { - 'Content-Type': 'application/json', - }; - } - } - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) { - if (response === undefined) { - return; // fallback to default error handler - } - if ('success' in response) { - // - // 1 - Liqui only returns the integer 'success' key from their private API - // - // { "success": 1, ... } httpCode === 200 - // { "success": 0, ... } httpCode === 200 - // - // 2 - However, exchanges derived from Liqui, can return non-integers - // - // It can be a numeric string - // { "sucesss": "1", ... } - // { "sucesss": "0", ... }, httpCode >= 200 (can be 403, 502, etc) - // - // Or just a string - // { "success": "true", ... } - // { "success": "false", ... }, httpCode >= 200 - // - // Or a boolean - // { "success": true, ... } - // { "success": false, ... }, httpCode >= 200 - // - // 3 - Oversimplified, Python PEP8 forbids comparison operator (===) of different types - // - // 4 - We do not want to copy-paste and duplicate the code of this handler to other exchanges derived from Liqui - // - // To cover points 1, 2, 3 and 4 combined this handler should work like this: - // - let success = this.safeValue (response, 'success', false); - if (typeof success === 'string') { - if ((success === 'true') || (success === '1')) { - success = true; - } else { - success = false; - } - } - if (!success) { - const code = this.safeString (response, 'code'); - const message = this.safeString (response, 'error'); - const feedback = this.id + ' ' + body; - this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback); - this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback); - throw new ExchangeError (feedback); // unknown message - } - } - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/equos.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/equos.js index 5dc44a2ac..0b90d79ed 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/equos.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/equos.js @@ -221,7 +221,7 @@ module.exports = class equos extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minTradeVol'), + 'min': this.safeNumber (market, 'minTradeVol'), 'max': undefined, }, 'price': { @@ -287,7 +287,7 @@ module.exports = class equos extends Exchange { const name = this.safeString (currency, 6); const status = this.safeInteger (currency, 4); const active = (status === 1); - const fee = this.safeFloat (currency, 5); // withdraw_fee + const fee = this.safeNumber (currency, 5); // withdraw_fee return { 'id': id, 'info': currency, @@ -379,8 +379,8 @@ module.exports = class equos extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); return [ this.convertFromScale (price, market['precision']['price']), this.convertFromScale (amount, market['precision']['amount']), @@ -526,9 +526,9 @@ module.exports = class equos extends Exchange { orderId = this.safeString (trade, 'orderId'); side = this.safeStringLower (trade, 'side'); type = this.parseOrderType (this.safeString (trade, 'ordType')); - price = this.safeFloat (trade, 'lastPx'); - amount = this.safeFloat (trade, 'quoteQty'); - let feeCost = this.safeFloat (trade, 'commission'); + price = this.safeNumber (trade, 'lastPx'); + amount = this.safeNumber (trade, 'quoteQty'); + let feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { feeCost = -feeCost; const feeCurrencyId = this.safeString (trade, 'commCurrency'); @@ -599,8 +599,8 @@ module.exports = class equos extends Exchange { if (assetType === 'ASSET') { const currencyId = this.safeString (position, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const quantity = this.safeFloat (position, 'quantity'); - const availableQuantity = this.safeFloat (position, 'availableQuantity'); + const quantity = this.safeNumber (position, 'quantity'); + const availableQuantity = this.safeNumber (position, 'availableQuantity'); const scale = this.safeInteger (position, 'quantity_scale'); const account = this.account (); account['free'] = this.convertFromScale (availableQuantity, scale); @@ -646,7 +646,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -743,7 +743,7 @@ module.exports = class equos extends Exchange { request['ordType'] = 2; request['price'] = this.convertToScale (price, this.getScale (price)); } else { - const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stopPx'); + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stopPx'); params = this.omit (params, [ 'stopPrice', 'stopPx' ]); if (stopPrice === undefined) { if (type === 'stop') { @@ -1116,7 +1116,7 @@ module.exports = class equos extends Exchange { address = undefined; } const type = this.safeString (transaction, 'type'); - let amount = this.safeFloat (transaction, 'balance_change'); + let amount = this.safeNumber (transaction, 'balance_change'); if (amount === undefined) { amount = this.safeInteger (transaction, 'quantity'); const amountScale = this.safeInteger (transaction, 'quantity_scale'); @@ -1199,8 +1199,8 @@ module.exports = class equos extends Exchange { for (let i = 0; i < tradingFees.length; i++) { const tradingFee = tradingFees[i]; if (this.safeString (tradingFee, 'tier') !== undefined) { - taker[tradingFee['tier']] = this.safeFloat (tradingFee, 'taker'); - maker[tradingFee['tier']] = this.safeFloat (tradingFee, 'maker'); + taker[tradingFee['tier']] = this.safeNumber (tradingFee, 'taker'); + maker[tradingFee['tier']] = this.safeNumber (tradingFee, 'maker'); } } return { @@ -1331,28 +1331,6 @@ module.exports = class equos extends Exchange { let remaining = this.safeInteger (order, 'leavesQty'); const remainingScale = this.safeInteger (order, 'leavesQty_scale'); remaining = this.convertFromScale (remaining, remainingScale); - if (remaining <= 0) { - if ((filled !== undefined) && (amount !== undefined) && (filled < amount)) { - remaining = undefined; - } - } - if ((remaining === undefined) && (amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0); - } - let average = this.safeInteger (order, 'price', 0); - if (average === 0) { - average = undefined; - } - const averageScale = this.safeInteger (order, 'price_scale'); - average = this.convertFromScale (average, averageScale); - let cost = undefined; - if (filled !== 0) { - if (average > 0) { - cost = average * filled; - } else if (price > 0) { - cost = price * filled; - } - } let fee = undefined; const currencyId = this.safeInteger (order, 'feeInstrumentId'); const feeCurrencyCode = this.safeCurrencyCode (currencyId); @@ -1375,7 +1353,7 @@ module.exports = class equos extends Exchange { } const stopPriceScale = this.safeInteger (order, 'stopPx_scale', 0); const stopPrice = this.convertFromScale (this.safeInteger (order, 'stopPx'), stopPriceScale); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, @@ -1390,14 +1368,14 @@ module.exports = class equos extends Exchange { 'price': price, 'stopPrice': stopPrice, 'amount': amount, - 'cost': cost, - 'average': average, + 'cost': undefined, + 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/eterbase.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/eterbase.js index 40d2893d3..531327d1d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/eterbase.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/eterbase.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, InvalidOrder, ExchangeError, BadRequest, BadSymbol } = require ('./base/errors'); const { TRUNCATE, SIGNIFICANT_DIGITS } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // ---------------------------------------------------------------------------- @@ -217,7 +218,7 @@ module.exports = class eterbase extends Exchange { const rule = rules[i]; const attribute = this.safeString (rule, 'attribute'); const condition = this.safeString (rule, 'condition'); - const value = this.safeFloat (rule, 'value'); + const value = this.safeNumber (rule, 'value'); if ((attribute === 'Qty') && (condition === 'Min')) { minAmount = value; } else if ((attribute === 'Qty') && (condition === 'Max')) { @@ -307,7 +308,7 @@ module.exports = class eterbase extends Exchange { 'type': type, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawalFee'), + 'fee': this.safeNumber (currency, 'withdrawalFee'), 'precision': precision, 'limits': { 'amount': { @@ -323,8 +324,8 @@ module.exports = class eterbase extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalMin'), - 'max': this.safeFloat (currency, 'withdrawalMax'), + 'min': this.safeNumber (currency, 'withdrawalMin'), + 'max': this.safeNumber (currency, 'withdrawalMax'), }, }, }; @@ -351,17 +352,17 @@ module.exports = class eterbase extends Exchange { const marketId = this.safeString (ticker, 'marketId'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const last = this.safeFloat (ticker, 'price'); - const baseVolume = this.safeFloat (ticker, 'volumeBase'); - const quoteVolume = this.safeFloat (ticker, 'volume'); + const last = this.safeNumber (ticker, 'price'); + const baseVolume = this.safeNumber (ticker, 'volumeBase'); + const quoteVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); - const percentage = this.safeFloat (ticker, 'change'); + const percentage = this.safeNumber (ticker, 'change'); const result = { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -403,14 +404,6 @@ module.exports = class eterbase extends Exchange { return this.parseTicker (response, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { @@ -465,10 +458,12 @@ module.exports = class eterbase extends Exchange { // "filledAt": 1556355722341 // } // - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -477,9 +472,9 @@ module.exports = class eterbase extends Exchange { 'currency': feeCurrencyCode, }; } - let cost = this.safeFloat (trade, 'qty'); - if ((cost === undefined) && (price !== undefined) && (amount !== undefined)) { - cost = price * amount; + let cost = this.safeNumber (trade, 'qty'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const timestamp = this.safeInteger2 (trade, 'executedAt', 'filledAt'); const tradeSide = this.safeString (trade, 'side'); @@ -577,11 +572,11 @@ module.exports = class eterbase extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -644,14 +639,13 @@ module.exports = class eterbase extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'assetId'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': this.safeFloat (balance, 'reserved'), - 'total': this.safeFloat (balance, 'balance'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -778,18 +772,18 @@ module.exports = class eterbase extends Exchange { } else { type = 'stoplimit'; } - let price = this.safeFloat (order, 'limitPrice'); - const amount = this.safeFloat (order, 'qty'); - let remaining = this.safeFloat (order, 'remainingQty'); + let price = this.safeNumber (order, 'limitPrice'); + const amount = this.safeNumber (order, 'qty'); + let remaining = this.safeNumber (order, 'remainingQty'); let filled = undefined; - const remainingCost = this.safeFloat (order, 'remainingCost'); + const remainingCost = this.safeNumber (order, 'remainingCost'); if ((remainingCost !== undefined) && (remainingCost === 0.0)) { remaining = 0; } if ((amount !== undefined) && (remaining !== undefined)) { filled = Math.max (0, amount - remaining); } - const cost = this.safeFloat (order, 'cost'); + const cost = this.safeNumber (order, 'cost'); if (type === 'market') { if (price === 0.0) { if ((cost !== undefined) && (filled !== undefined)) { @@ -806,7 +800,7 @@ module.exports = class eterbase extends Exchange { } } const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -979,7 +973,7 @@ module.exports = class eterbase extends Exchange { } if ((uppercaseType === 'MARKET') && (uppercaseSide === 'BUY')) { // for market buy it requires the amount of quote currency to spend - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); if (this.options['createMarketBuyOrderRequiresPrice']) { if (cost === undefined) { if (price !== undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exmo.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exmo.js index c9e19479d..d79e42079 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exmo.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exmo.js @@ -112,6 +112,7 @@ module.exports = class exmo extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.2 / 100, @@ -581,18 +582,18 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = marketId.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const maxAmount = this.safeFloat (limit, 'max_q'); - const maxPrice = this.safeFloat (limit, 'max_p'); - const maxCost = this.safeFloat (limit, 'max_a'); - const minAmount = this.safeFloat (limit, 'min_q'); - const minPrice = this.safeFloat (limit, 'min_p'); - const minCost = this.safeFloat (limit, 'min_a'); - minAmounts[base] = Math.min (this.safeFloat (minAmounts, base, minAmount), minAmount); - maxAmounts[base] = Math.max (this.safeFloat (maxAmounts, base, maxAmount), maxAmount); - minPrices[quote] = Math.min (this.safeFloat (minPrices, quote, minPrice), minPrice); - minCosts[quote] = Math.min (this.safeFloat (minCosts, quote, minCost), minCost); - maxPrices[quote] = Math.max (this.safeFloat (maxPrices, quote, maxPrice), maxPrice); - maxCosts[quote] = Math.max (this.safeFloat (maxCosts, quote, maxCost), maxCost); + const maxAmount = this.safeNumber (limit, 'max_q'); + const maxPrice = this.safeNumber (limit, 'max_p'); + const maxCost = this.safeNumber (limit, 'max_a'); + const minAmount = this.safeNumber (limit, 'min_q'); + const minPrice = this.safeNumber (limit, 'min_p'); + const minCost = this.safeNumber (limit, 'min_a'); + minAmounts[base] = Math.min (this.safeNumber (minAmounts, base, minAmount), minAmount); + maxAmounts[base] = Math.max (this.safeNumber (maxAmounts, base, maxAmount), maxAmount); + minPrices[quote] = Math.min (this.safeNumber (minPrices, quote, minPrice), minPrice); + minCosts[quote] = Math.min (this.safeNumber (minCosts, quote, minCost), minCost); + maxPrices[quote] = Math.max (this.safeNumber (maxPrices, quote, maxPrice), maxPrice); + maxCosts[quote] = Math.max (this.safeNumber (maxCosts, quote, maxCost), maxCost); } const result = {}; for (let i = 0; i < ids.length; i++) { @@ -609,16 +610,16 @@ module.exports = class exmo extends Exchange { 'precision': 8, 'limits': { 'amount': { - 'min': this.safeFloat (minAmounts, code), - 'max': this.safeFloat (maxAmounts, code), + 'min': this.safeNumber (minAmounts, code), + 'max': this.safeNumber (maxAmounts, code), }, 'price': { - 'min': this.safeFloat (minPrices, code), - 'max': this.safeFloat (maxPrices, code), + 'min': this.safeNumber (minPrices, code), + 'max': this.safeNumber (maxPrices, code), }, 'cost': { - 'min': this.safeFloat (minCosts, code), - 'max': this.safeFloat (maxCosts, code), + 'min': this.safeNumber (minCosts, code), + 'max': this.safeNumber (maxCosts, code), }, }, 'info': id, @@ -653,8 +654,8 @@ module.exports = class exmo extends Exchange { const [ baseId, quoteId ] = symbol.split ('/'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); - const taker = this.safeFloat (market, 'commission_taker_percent'); - const maker = this.safeFloat (market, 'commission_maker_percent'); + const taker = this.safeNumber (market, 'commission_taker_percent'); + const maker = this.safeNumber (market, 'commission_maker_percent'); result.push ({ 'id': id, 'symbol': symbol, @@ -667,16 +668,16 @@ module.exports = class exmo extends Exchange { 'maker': maker / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, }, 'precision': { @@ -749,11 +750,11 @@ module.exports = class exmo extends Exchange { // return [ this.safeInteger (ohlcv, 't'), - this.safeFloat (ohlcv, 'o'), - this.safeFloat (ohlcv, 'h'), - this.safeFloat (ohlcv, 'l'), - this.safeFloat (ohlcv, 'c'), - this.safeFloat (ohlcv, 'v'), + this.safeNumber (ohlcv, 'o'), + this.safeNumber (ohlcv, 'h'), + this.safeNumber (ohlcv, 'l'), + this.safeNumber (ohlcv, 'c'), + this.safeNumber (ohlcv, 'v'), ]; } @@ -769,14 +770,14 @@ module.exports = class exmo extends Exchange { const currencyId = this.currencyId (code); const account = this.account (); if (currencyId in free) { - account['free'] = this.safeFloat (free, currencyId); + account['free'] = this.safeString (free, currencyId); } if (currencyId in used) { - account['used'] = this.safeFloat (used, currencyId); + account['used'] = this.safeString (used, currencyId); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -834,16 +835,16 @@ module.exports = class exmo extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy_price'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy_price'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell_price'), + 'ask': this.safeNumber (ticker, 'sell_price'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -852,9 +853,9 @@ module.exports = class exmo extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'vol_curr'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'vol_curr'), 'info': ticker, }; } @@ -915,9 +916,9 @@ module.exports = class exmo extends Exchange { let symbol = undefined; const id = this.safeString (trade, 'trade_id'); const orderId = this.safeString (trade, 'order_id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'quantity'); + const cost = this.safeNumber (trade, 'amount'); const side = this.safeString (trade, 'type'); const type = undefined; const marketId = this.safeString (trade, 'pair'); @@ -936,11 +937,11 @@ module.exports = class exmo extends Exchange { } const takerOrMaker = this.safeString (trade, 'exec_type'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission_amount'); + const feeCost = this.safeNumber (trade, 'commission_amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commission_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (trade, 'commission_percent'); + let feeRate = this.safeNumber (trade, 'commission_percent'); if (feeRate !== undefined) { feeRate /= 1000; } @@ -1239,13 +1240,13 @@ module.exports = class exmo extends Exchange { market = this.markets_by_id[marketId]; } } - let amount = this.safeFloat (order, 'quantity'); + let amount = this.safeNumber (order, 'quantity'); if (amount === undefined) { const amountField = (side === 'buy') ? 'in_amount' : 'out_amount'; - amount = this.safeFloat (order, amountField); + amount = this.safeNumber (order, amountField); } - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'amount'); + let price = this.safeNumber (order, 'price'); + let cost = this.safeNumber (order, 'amount'); let filled = 0.0; const trades = []; const transactions = this.safeValue (order, 'trades', []); @@ -1366,24 +1367,6 @@ module.exports = class exmo extends Exchange { return undefined; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { await this.loadMarkets (); const currency = this.currency (code); @@ -1428,7 +1411,7 @@ module.exports = class exmo extends Exchange { // } // const timestamp = this.safeTimestamp (transaction, 'dt'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -1458,7 +1441,7 @@ module.exports = class exmo extends Exchange { // fixed funding fees only (for now) if (!this.fees['funding']['percentage']) { const key = (type === 'withdrawal') ? 'withdraw' : 'deposit'; - let feeCost = this.safeFloat (this.options['fundingFees'][key], code); + let feeCost = this.safeNumber (this.options['fundingFees'][key], code); // users don't pay for cashbacks, no fees for that const provider = this.safeString (transaction, 'provider'); if (provider === 'cashback') { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exx.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exx.js index c4c12d03f..72b59ef1b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exx.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/exx.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ExchangeNotAvailable, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -148,26 +149,26 @@ module.exports = class exx extends Exchange { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); ticker = ticker['ticker']; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'riseRate'), + 'change': this.safeNumber (ticker, 'riseRate'), 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -217,14 +218,11 @@ module.exports = class exx extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -269,14 +267,13 @@ module.exports = class exx extends Exchange { const currencyId = currencies[i]; const balance = balances[currencyId]; const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'balance'), - 'used': this.safeFloat (balance, 'freeze'), - 'total': this.safeFloat (balance, 'total'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'freeze'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { @@ -296,11 +293,10 @@ module.exports = class exx extends Exchange { // const symbol = market['symbol']; const timestamp = parseInt (order['trade_date']); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'trade_money'); - const amount = this.safeFloat (order, 'total_amount'); - const filled = this.safeFloat (order, 'trade_amount', 0.0); - const remaining = parseFloat (this.amountToPrecision (symbol, amount - filled)); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'trade_money'); + const amount = this.safeNumber (order, 'total_amount'); + const filled = this.safeNumber (order, 'trade_amount', 0.0); let status = this.safeInteger (order, 'status'); if (status === 1) { status = 'canceled'; @@ -312,11 +308,11 @@ module.exports = class exx extends Exchange { let fee = undefined; if ('fees' in order) { fee = { - 'cost': this.safeFloat (order, 'fees'), + 'cost': this.safeNumber (order, 'fees'), 'currency': market['quote'], }; } - return { + return this.safeOrder ({ 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -333,12 +329,12 @@ module.exports = class exx extends Exchange { 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/fcoin.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/fcoin.js index 2d1c845ab..2d90e7cce 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/fcoin.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/fcoin.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeError, ExchangeNotAvailable, ArgumentsRequired, InsufficientFunds, InvalidOrder, RateLimitExceeded, InvalidNonce, AuthenticationError, NotSupported } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -223,8 +224,8 @@ module.exports = class fcoin extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'limit_amount_min'), - 'max': this.safeFloat (market, 'limit_amount_max'), + 'min': this.safeNumber (market, 'limit_amount_min'), + 'max': this.safeNumber (market, 'limit_amount_max'), }, 'price': { 'min': Math.pow (10, -precision['price']), @@ -319,12 +320,12 @@ module.exports = class fcoin extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseBidsAsks (orders, priceKey = 0, amountKey = 1) { @@ -337,8 +338,8 @@ module.exports = class fcoin extends Exchange { const priceField = this.sum (index, priceKey); const amountField = this.sum (index, amountKey); result.push ([ - this.safeFloat (orders, priceField), - this.safeFloat (orders, amountField), + this.safeNumber (orders, priceField), + this.safeNumber (orders, amountField), ]); } return result; @@ -386,17 +387,17 @@ module.exports = class fcoin extends Exchange { } } const values = ticker['ticker']; - const last = this.safeFloat (values, 0); + const last = this.safeNumber (values, 0); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (values, 7), - 'low': this.safeFloat (values, 8), - 'bid': this.safeFloat (values, 2), - 'bidVolume': this.safeFloat (values, 3), - 'ask': this.safeFloat (values, 4), - 'askVolume': this.safeFloat (values, 5), + 'high': this.safeNumber (values, 7), + 'low': this.safeNumber (values, 8), + 'bid': this.safeNumber (values, 2), + 'bidVolume': this.safeNumber (values, 3), + 'ask': this.safeNumber (values, 4), + 'askVolume': this.safeNumber (values, 5), 'vwap': undefined, 'open': undefined, 'close': last, @@ -405,8 +406,8 @@ module.exports = class fcoin extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (values, 9), - 'quoteVolume': this.safeFloat (values, 10), + 'baseVolume': this.safeNumber (values, 9), + 'quoteVolume': this.safeNumber (values, 10), 'info': ticker, }; } @@ -419,14 +420,11 @@ module.exports = class fcoin extends Exchange { const timestamp = this.safeInteger (trade, 'ts'); const side = this.safeStringLower (trade, 'side'); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = undefined; return { 'id': id, @@ -551,38 +549,25 @@ module.exports = class fcoin extends Exchange { const symbol = market['symbol']; const orderType = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'created_at'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'filled_amount'); - let remaining = undefined; - let price = this.safeFloat (order, 'price'); - let cost = this.safeFloat (order, 'executed_value'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } else if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'filled_amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'executed_value'); let feeCurrency = undefined; let feeCost = undefined; - const feeRebate = this.safeFloat (order, 'fees_income'); + const feeRebate = this.safeNumber (order, 'fees_income'); if ((feeRebate !== undefined) && (feeRebate > 0)) { if (market !== undefined) { feeCurrency = (side === 'buy') ? market['quote'] : market['base']; } feeCost = -feeRebate; } else { - feeCost = this.safeFloat (order, 'fill_fees'); + feeCost = this.safeNumber (order, 'fill_fees'); if (market !== undefined) { feeCurrency = (side === 'buy') ? market['base'] : market['quote']; } } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -598,7 +583,7 @@ module.exports = class fcoin extends Exchange { 'stopPrice': undefined, 'cost': cost, 'amount': amount, - 'remaining': remaining, + 'remaining': undefined, 'filled': filled, 'average': undefined, 'status': status, @@ -607,7 +592,7 @@ module.exports = class fcoin extends Exchange { 'currency': feeCurrency, }, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -649,11 +634,11 @@ module.exports = class fcoin extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_vol'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_vol'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/flowbtc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/flowbtc.js index 12646489b..45d80935d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/flowbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/flowbtc.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -131,11 +132,11 @@ module.exports = class flowbtc extends Exchange { const currencyId = balance['name']; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['total'] = this.safeFloat (balance, 'hold'); + account['free'] = this.safeString (balance, 'balance'); + account['total'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -156,16 +157,16 @@ module.exports = class flowbtc extends Exchange { }; const ticker = await this.publicPostGetTicker (this.extend (request, params)); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -175,8 +176,8 @@ module.exports = class flowbtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume24hr'), - 'quoteVolume': this.safeFloat (ticker, 'volume24hrProduct2'), + 'baseVolume': this.safeNumber (ticker, 'volume24hr'), + 'quoteVolume': this.safeNumber (ticker, 'volume24hrProduct2'), 'info': ticker, }; } @@ -185,14 +186,11 @@ module.exports = class flowbtc extends Exchange { const timestamp = this.safeTimestamp (trade, 'unixtime'); const side = (trade['incomingOrderSide'] === 0) ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'px'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'px'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'timestamp': timestamp, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/foxbit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/foxbit.js index 5830969a3..b1fb3032b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/foxbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/foxbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89,11 +90,11 @@ module.exports = class foxbit extends Exchange { // otherwise we will lose the info if the currency balance has been funded or traded or not if (currencyId in balances) { const account = this.account (); - let used = this.safeFloat (balances, currencyId + '_locked'); + let used = this.safeNumber (balances, currencyId + '_locked'); if (used !== undefined) { used *= 1e-8; } - let total = this.safeFloat (balances, currencyId); + let total = this.safeNumber (balances, currencyId); if (total !== undefined) { total *= 1e-8; } @@ -128,16 +129,16 @@ module.exports = class foxbit extends Exchange { const timestamp = this.milliseconds (); const lowercaseQuote = market['quote'].toLowerCase (); const quoteVolume = 'vol_' + lowercaseQuote; - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -147,8 +148,8 @@ module.exports = class foxbit extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -161,14 +162,11 @@ module.exports = class foxbit extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ftx.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ftx.js index 18b572cc6..a0e42e8e4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ftx.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ftx.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending } = require ('./base/errors'); +const { ExchangeError, InvalidOrder, BadRequest, InsufficientFunds, OrderNotFound, AuthenticationError, RateLimitExceeded, ExchangeNotAvailable, CancelPending, ArgumentsRequired, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -243,6 +244,7 @@ module.exports = class ftx extends Exchange { 'An unexpected error occurred': ExchangeNotAvailable, // {"error":"An unexpected error occurred, please try again later (58BC21C795).","success":false} 'Please retry request': ExchangeNotAvailable, // {"error":"Please retry request","success":false} 'Please try again': ExchangeNotAvailable, // {"error":"Please try again","success":false} + 'Only have permissions for subaccount': PermissionDenied, // {"success":false,"error":"Only have permissions for subaccount *sub_name*"} }, }, 'precisionMode': TICK_SIZE, @@ -366,8 +368,8 @@ module.exports = class ftx extends Exchange { // check if a market is a spot or future market const symbol = (type === 'future') ? this.safeString (market, 'name') : (base + '/' + quote); const active = this.safeValue (market, 'enabled'); - const sizeIncrement = this.safeFloat (market, 'sizeIncrement'); - const priceIncrement = this.safeFloat (market, 'priceIncrement'); + const sizeIncrement = this.safeNumber (market, 'sizeIncrement'); + const priceIncrement = this.safeNumber (market, 'priceIncrement'); const precision = { 'amount': sizeIncrement, 'price': priceIncrement, @@ -445,28 +447,28 @@ module.exports = class ftx extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); const timestamp = this.safeTimestamp (ticker, 'time', this.milliseconds ()); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidSize'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askSize'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidSize'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askSize'), 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'change24h'), + 'percentage': this.safeNumber (ticker, 'change24h'), 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'quoteVolume24h'), + 'quoteVolume': this.safeNumber (ticker, 'quoteVolume24h'), 'info': ticker, }; } @@ -506,14 +508,6 @@ module.exports = class ftx extends Exchange { return this.parseTicker (result, market); } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetMarkets (params); @@ -592,11 +586,11 @@ module.exports = class ftx extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -717,6 +711,45 @@ module.exports = class ftx extends Exchange { // "type": "otc" // } // + // with -ve fee + // { + // "id": 1171258927, + // "fee": -0.0000713875, + // "side": "sell", + // "size": 1, + // "time": "2021-03-11T13:34:35.523627+00:00", + // "type": "order", + // "price": 14.2775, + // "future": null, + // "market": "SOL/USD", + // "feeRate": -0.000005, + // "orderId": 33182929044, + // "tradeId": 582936801, + // "liquidity": "maker", + // "feeCurrency": "USD", + // "baseCurrency": "SOL", + // "quoteCurrency": "USD" + // } + // + // // from OTC order + // { + // "id": 1172129651, + // "fee": 0, + // "side": "sell", + // "size": 1.47568846, + // "time": "2021-03-11T15:04:46.893383+00:00", + // "type": "otc", + // "price": 14.60932598, + // "future": null, + // "market": null, + // "feeRate": 0, + // "orderId": null, + // "tradeId": null, + // "liquidity": "taker", + // "feeCurrency": "USD", + // "baseCurrency": "BCHA", + // "quoteCurrency": "USD" + // } const id = this.safeString (trade, 'id'); const takerOrMaker = this.safeString (trade, 'liquidity'); const marketId = this.safeString (trade, 'market'); @@ -734,25 +767,24 @@ module.exports = class ftx extends Exchange { } } const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (price !== undefined && amount !== undefined) { - cost = price * amount; - } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } const orderId = this.safeString (trade, 'orderId'); @@ -858,8 +890,8 @@ module.exports = class ftx extends Exchange { const result = this.safeValue (response, 'result', {}); return { 'info': response, - 'maker': this.safeFloat (result, 'makerFee'), - 'taker': this.safeFloat (result, 'takerFee'), + 'maker': this.safeNumber (result, 'makerFee'), + 'taker': this.safeNumber (result, 'takerFee'), }; } @@ -886,11 +918,11 @@ module.exports = class ftx extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'coin')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'free'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -1013,9 +1045,9 @@ module.exports = class ftx extends Exchange { const id = this.safeString (order, 'id'); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); let status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filledSize'); - let remaining = this.safeFloat (order, 'remainingSize'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filledSize'); + let remaining = this.safeNumber (order, 'remainingSize'); if ((remaining === 0.0) && (amount !== undefined) && (filled !== undefined)) { remaining = Math.max (amount - filled, 0); if (remaining > 0) { @@ -1039,15 +1071,15 @@ module.exports = class ftx extends Exchange { } const side = this.safeString (order, 'side'); const type = this.safeString (order, 'type'); - const average = this.safeFloat (order, 'avgFillPrice'); - const price = this.safeFloat2 (order, 'price', 'triggerPrice', average); + const average = this.safeNumber (order, 'avgFillPrice'); + const price = this.safeNumber2 (order, 'price', 'triggerPrice', average); let cost = undefined; if (filled !== undefined && price !== undefined) { cost = filled * price; } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'triggeredAt')); const clientOrderId = this.safeString (order, 'clientId'); - const stopPrice = this.safeFloat (order, 'triggerPrice'); + const stopPrice = this.safeNumber (order, 'triggerPrice'); const postOnly = this.safeValue (order, 'postOnly'); return { 'info': order, @@ -1093,22 +1125,28 @@ module.exports = class ftx extends Exchange { request['clientId'] = clientOrderId; params = this.omit (params, [ 'clientId', 'clientOrderId' ]); } - let priceToPrecision = undefined; - if (price !== undefined) { - priceToPrecision = parseFloat (this.priceToPrecision (symbol, price)); - } - let method = 'privatePostConditionalOrders'; + let method = undefined; if (type === 'limit') { method = 'privatePostOrders'; - request['price'] = priceToPrecision; + request['price'] = parseFloat (this.priceToPrecision (symbol, price)); } else if (type === 'market') { method = 'privatePostOrders'; request['price'] = null; } else if ((type === 'stop') || (type === 'takeProfit')) { - request['triggerPrice'] = priceToPrecision; - // request['orderPrice'] = number; // optional, order type is limit if this is specified, otherwise market + method = 'privatePostConditionalOrders'; + const stopPrice = this.safeNumber2 (params, 'stopPrice', 'triggerPrice'); + if (stopPrice === undefined) { + throw new ArgumentsRequired (this.id + ' createOrder () requires a stopPrice parameter or a triggerPrice parameter for ' + type + ' orders'); + } else { + params = this.omit (params, [ 'stopPrice', 'triggerPrice' ]); + request['triggerPrice'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + } + if (price !== undefined) { + request['orderPrice'] = parseFloat (this.priceToPrecision (symbol, price)); // optional, order type is limit if this is specified, otherwise market + } } else if (type === 'trailingStop') { - request['trailValue'] = priceToPrecision; // negative for "sell", positive for "buy" + method = 'privatePostConditionalOrders'; + request['trailValue'] = parseFloat (this.priceToPrecision (symbol, price)); // negative for "sell", positive for "buy" } else { throw new InvalidOrder (this.id + ' createOrder () does not support order type ' + type + ', only limit, market, stop, trailingStop, or takeProfit orders are supported'); } @@ -1174,9 +1212,9 @@ module.exports = class ftx extends Exchange { const request = {}; let method = undefined; const clientOrderId = this.safeString2 (params, 'client_order_id', 'clientOrderId'); - const triggerPrice = this.safeFloat (params, 'triggerPrice'); - const orderPrice = this.safeFloat (params, 'orderPrice'); - const trailValue = this.safeFloat (params, 'trailValue'); + const triggerPrice = this.safeNumber (params, 'triggerPrice'); + const orderPrice = this.safeNumber (params, 'orderPrice'); + const trailValue = this.safeNumber (params, 'trailValue'); params = this.omit (params, [ 'client_order_id', 'clientOrderId', 'triggerPrice', 'orderPrice', 'trailValue' ]); const triggerPriceIsDefined = (triggerPrice !== undefined); const orderPriceIsDefined = (orderPrice !== undefined); @@ -1539,7 +1577,7 @@ module.exports = class ftx extends Exchange { return this.parseTransaction (result, currency); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetAccount (params); // @@ -1672,7 +1710,7 @@ module.exports = class ftx extends Exchange { // const code = this.safeCurrencyCode (this.safeString (transaction, 'coin')); const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'size'); + const amount = this.safeNumber (transaction, 'size'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const timestamp = this.parse8601 (this.safeString (transaction, 'time')); const txid = this.safeString (transaction, 'txid'); @@ -1689,7 +1727,7 @@ module.exports = class ftx extends Exchange { address = notes.slice (12); } } - const fee = this.safeFloat (transaction, 'fee'); + const fee = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gateio.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gateio.js index f0835c774..eac7234c9 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gateio.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gateio.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, ArgumentsRequired, InvalidAddress, OrderNotFound, NotSupported, DDoSProtection, InsufficientFunds, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,9 +165,12 @@ module.exports = class gateio extends Exchange { }, }, 'commonCurrencies': { + '88MPH': 'MPH', + 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', + 'MPH': 'Morpher', // conflict with 88MPH 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', }, @@ -213,9 +217,9 @@ module.exports = class gateio extends Exchange { const currency = coin[id]; const code = this.safeCurrencyCode (id); const delisted = this.safeValue (currency, 'delisted', 0); - const withdrawDisabled = this.safeValue (currency, 'withdraw_disabled', 0); - const depositDisabled = this.safeValue (currency, 'deposit_disabled', 0); - const tradeDisabled = this.safeValue (currency, 'trade_disabled', 0); + const withdrawDisabled = this.safeInteger2 (currency, 'withdraw_disabled', 0); + const depositDisabled = this.safeInteger2 (currency, 'deposit_disabled', 0); + const tradeDisabled = this.safeInteger2 (currency, 'trade_disabled', 0); const listed = (delisted === 0); const withdrawEnabled = (withdrawDisabled === 0); const depositEnabled = (depositDisabled === 0); @@ -304,7 +308,7 @@ module.exports = class gateio extends Exchange { 'price': this.safeInteger (details, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (details, 'min_amount'), + 'min': this.safeNumber (details, 'min_amount'), 'max': undefined, }; const priceLimits = { @@ -312,7 +316,7 @@ module.exports = class gateio extends Exchange { 'max': undefined, }; const defaultCost = amountLimits['min'] * priceLimits['min']; - const minCost = this.safeFloat (this.options['limits']['cost']['min'], quote, defaultCost); + const minCost = this.safeNumber (this.options['limits']['cost']['min'], quote, defaultCost); const costLimits = { 'min': minCost, 'max': undefined, @@ -322,10 +326,10 @@ module.exports = class gateio extends Exchange { 'price': priceLimits, 'cost': costLimits, }; - const disabled = this.safeValue (details, 'trade_disabled'); + const disabled = this.safeInteger (details, 'trade_disabled'); const active = !disabled; const uppercaseId = id.toUpperCase (); - const fee = this.safeFloat (details, 'fee'); + const fee = this.safeNumber (details, 'fee'); result.push ({ 'id': id, 'uppercaseId': uppercaseId, @@ -359,11 +363,11 @@ module.exports = class gateio extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (available, currencyId); - account['used'] = this.safeFloat (locked, currencyId); + account['free'] = this.safeString (available, currencyId); + account['used'] = this.safeString (locked, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -379,11 +383,11 @@ module.exports = class gateio extends Exchange { // they return [ Timestamp, Volume, Close, High, Low, Open ] return [ this.safeInteger (ohlcv, 0), // t - this.safeFloat (ohlcv, 5), // o - this.safeFloat (ohlcv, 3), // h - this.safeFloat (ohlcv, 4), // l - this.safeFloat (ohlcv, 2), // c - this.safeFloat (ohlcv, 1), // v + this.safeNumber (ohlcv, 5), // o + this.safeNumber (ohlcv, 3), // h + this.safeNumber (ohlcv, 4), // l + this.safeNumber (ohlcv, 2), // c + this.safeNumber (ohlcv, 1), // v ]; } @@ -395,11 +399,11 @@ module.exports = class gateio extends Exchange { 'group_sec': this.timeframes[timeframe], }; // max limit = 1001 - if (limit !== undefined) { - const periodDurationInSeconds = this.parseTimeframe (timeframe); - const hours = parseInt ((periodDurationInSeconds * limit) / 3600); - request['range_hour'] = Math.max (0, hours - 1); - } + // if (limit !== undefined) { + // const periodDurationInSeconds = this.parseTimeframe (timeframe); + // const hours = parseInt ((periodDurationInSeconds * limit) / 3600); + // request['range_hour'] = Math.max (1, hours - 1); + // } const response = await this.publicGetCandlestick2Id (this.extend (request, params)); // // { @@ -423,8 +427,8 @@ module.exports = class gateio extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'percentChange'); let open = undefined; let change = undefined; let average = undefined; @@ -434,17 +438,17 @@ module.exports = class gateio extends Exchange { change = last - open; average = this.sum (last, open) / 2; } - open = this.safeFloat (ticker, 'open', open); - change = this.safeFloat (ticker, 'change', change); + open = this.safeNumber (ticker, 'open', open); + change = this.safeNumber (ticker, 'change', change); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat2 (ticker, 'high24hr', 'high'), - 'low': this.safeFloat2 (ticker, 'low24hr', 'low'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber2 (ticker, 'high24hr', 'high'), + 'low': this.safeNumber2 (ticker, 'low24hr', 'low'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -454,8 +458,8 @@ module.exports = class gateio extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), // gateio has them reversed - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), // gateio has them reversed + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -501,27 +505,24 @@ module.exports = class gateio extends Exchange { const id = this.safeString2 (trade, 'tradeID', 'id'); // take either of orderid or orderId const orderId = this.safeString2 (trade, 'orderid', 'orderNumber'); - const price = this.safeFloat2 (trade, 'rate', 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString2 (trade, 'rate', 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = this.safeString (trade, 'type'); const takerOrMaker = this.safeString (trade, 'role'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } let fee = undefined; let feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee_coin')); - let feeCost = this.safeFloat (trade, 'point_fee'); + let feeCost = this.safeNumber (trade, 'point_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'gt_fee'); + feeCost = this.safeNumber (trade, 'gt_fee'); if ((feeCost === undefined) || (feeCost === 0)) { - feeCost = this.safeFloat (trade, 'fee'); + feeCost = this.safeNumber (trade, 'fee'); } else { feeCurrency = this.safeCurrencyCode ('GT'); } @@ -665,23 +666,20 @@ module.exports = class gateio extends Exchange { } else if (side === '2') { side = 'buy'; } - const price = this.safeFloat2 (order, 'initialRate', 'rate'); - const average = this.safeFloat (order, 'filledRate'); - const amount = this.safeFloat2 (order, 'initialAmount', 'amount'); - const filled = this.safeFloat (order, 'filledAmount'); + const price = this.safeNumber2 (order, 'initialRate', 'rate'); + const average = this.safeNumber (order, 'filledRate'); + const amount = this.safeNumber2 (order, 'initialAmount', 'amount'); + const filled = this.safeNumber (order, 'filledAmount'); // In the order status response, this field has a different name. - let remaining = this.safeFloat2 (order, 'leftAmount', 'left'); - if (remaining === undefined) { - remaining = amount - filled; - } - const feeCost = this.safeFloat (order, 'feeValue'); + const remaining = this.safeNumber2 (order, 'leftAmount', 'left'); + const feeCost = this.safeNumber (order, 'feeValue'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - let feeRate = this.safeFloat (order, 'feePercentage'); + let feeRate = this.safeNumber (order, 'feePercentage'); if (feeRate !== undefined) { feeRate = feeRate / 100; } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -707,7 +705,7 @@ module.exports = class gateio extends Exchange { 'rate': feeRate, }, 'info': order, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -898,7 +896,7 @@ module.exports = class gateio extends Exchange { const code = this.safeCurrencyCode (currencyId, currency); const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'txid'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); if (address === 'false') { address = undefined; @@ -906,7 +904,7 @@ module.exports = class gateio extends Exchange { const timestamp = this.safeTimestamp (transaction, 'timestamp'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.parseTransactionType (id[0]); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gemini.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gemini.js index 6f28ef220..36892fa47 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gemini.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gemini.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidOrder, InvalidNonce, InsufficientFunds, AuthenticationError, PermissionDenied, NotSupported, OnMaintenance, RateLimitExceeded, ExchangeNotAvailable } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -221,16 +222,16 @@ module.exports = class gemini extends Exchange { // const base = this.safeCurrencyCode (baseId); const minAmountString = cells[1].replace ('', ''); const minAmountParts = minAmountString.split (' '); - const minAmount = this.safeFloat (minAmountParts, 0); + const minAmount = this.safeNumber (minAmountParts, 0); const amountPrecisionString = cells[2].replace ('', ''); const amountPrecisionParts = amountPrecisionString.split (' '); - const amountPrecision = this.safeFloat (amountPrecisionParts, 0); + const amountPrecision = this.safeNumber (amountPrecisionParts, 0); const idLength = marketId.length - 0; const quoteId = marketId.slice (idLength - 3, idLength); const quote = this.safeCurrencyCode (quoteId); const pricePrecisionString = cells[3].replace ('', ''); const pricePrecisionParts = pricePrecisionString.split (' '); - const pricePrecision = this.safeFloat (pricePrecisionParts, 0); + const pricePrecision = this.safeNumber (pricePrecisionParts, 0); const baseId = marketId.replace (quoteId, ''); const base = this.safeCurrencyCode (baseId); const symbol = base + '/' + quote; @@ -458,11 +459,11 @@ module.exports = class gemini extends Exchange { base = market['base']; quote = market['quote']; } - const price = this.safeFloat (ticker, 'price'); - const last = this.safeFloat2 (ticker, 'last', 'close', price); - let percentage = this.safeFloat (ticker, 'percentChange24h'); + const price = this.safeNumber (ticker, 'price'); + const last = this.safeNumber2 (ticker, 'last', 'close', price); + let percentage = this.safeNumber (ticker, 'percentChange24h'); let change = undefined; - let open = this.safeFloat (ticker, 'open'); + let open = this.safeNumber (ticker, 'open'); let average = undefined; if (last !== undefined) { if (open !== undefined) { @@ -479,18 +480,18 @@ module.exports = class gemini extends Exchange { average = this.sum (last, open) / 2; } } - const baseVolume = this.safeFloat (volume, baseId); - const quoteVolume = this.safeFloat (volume, quoteId); + const baseVolume = this.safeNumber (volume, baseId); + const quoteVolume = this.safeNumber (volume, quoteId); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -506,14 +507,6 @@ module.exports = class gemini extends Exchange { }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetV1Pricefeed (params); @@ -554,17 +547,14 @@ module.exports = class gemini extends Exchange { const feeCurrencyId = this.safeString (trade, 'fee_currency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); const fee = { - 'cost': this.safeFloat (trade, 'fee_amount'), + 'cost': this.safeNumber (trade, 'fee_amount'), 'currency': feeCurrencyCode, }; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = undefined; const side = this.safeStringLower (trade, 'type'); const symbol = this.safeSymbol (undefined, market); @@ -617,18 +607,18 @@ module.exports = class gemini extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'amount'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrder (order, market = undefined) { const timestamp = this.safeInteger (order, 'timestampms'); - const amount = this.safeFloat (order, 'original_amount'); - const remaining = this.safeFloat (order, 'remaining_amount'); - const filled = this.safeFloat (order, 'executed_amount'); + const amount = this.safeNumber (order, 'original_amount'); + const remaining = this.safeNumber (order, 'remaining_amount'); + const filled = this.safeNumber (order, 'executed_amount'); let status = 'closed'; if (order['is_live']) { status = 'open'; @@ -636,14 +626,8 @@ module.exports = class gemini extends Exchange { if (order['is_cancelled']) { status = 'canceled'; } - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'avg_execution_price'); - let cost = undefined; - if (filled !== undefined) { - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'avg_execution_price'); let type = this.safeString (order, 'type'); if (type === 'exchange limit') { type = 'limit'; @@ -658,7 +642,7 @@ module.exports = class gemini extends Exchange { const id = this.safeString (order, 'order_id'); const side = this.safeStringLower (order, 'side'); const clientOrderId = this.safeString (order, 'client_order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -674,13 +658,13 @@ module.exports = class gemini extends Exchange { 'price': price, 'stopPrice': undefined, 'average': average, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'remaining': remaining, 'fee': fee, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -795,7 +779,7 @@ module.exports = class gemini extends Exchange { status = 'ok'; } let fee = undefined; - const feeAmount = this.safeFloat (transaction, 'feeAmount'); + const feeAmount = this.safeNumber (transaction, 'feeAmount'); if (feeAmount !== undefined) { fee = { 'cost': feeAmount, @@ -811,7 +795,7 @@ module.exports = class gemini extends Exchange { 'address': address, 'tag': undefined, // or is it defined? 'type': type, // direction of the transaction, ('deposit' | 'withdraw') - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gopax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gopax.js index e3150163a..b27308f19 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gopax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/gopax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors'); const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -218,8 +219,8 @@ module.exports = class gopax extends Exchange { const minimums = this.safeValue (market, 'restApiOrderAmountMin', {}); const marketAsk = this.safeValue (minimums, 'marketAsk', {}); const marketBid = this.safeValue (minimums, 'marketBid', {}); - const takerFeePercent = this.safeFloat (market, 'takerFeePercent'); - const makerFeePercent = this.safeFloat (market, 'makerFeePercent'); + const takerFeePercent = this.safeNumber (market, 'takerFeePercent'); + const makerFeePercent = this.safeNumber (market, 'makerFeePercent'); const taker = parseFloat (this.decimalToPrecision (takerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); const maker = parseFloat (this.decimalToPrecision (makerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE)); result.push ({ @@ -237,15 +238,15 @@ module.exports = class gopax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (marketAsk, 'amount'), + 'min': this.safeNumber (marketAsk, 'amount'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'priceMin'), + 'min': this.safeNumber (market, 'priceMin'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (marketBid, 'amount'), + 'min': this.safeNumber (marketBid, 'amount'), 'max': undefined, }, }, @@ -280,8 +281,8 @@ module.exports = class gopax extends Exchange { const id = this.safeString (currency, 'id'); const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'name'); - const fee = this.safeFloat (currency, 'withdrawalFee'); - const precision = this.safeFloat (currency, 'scale'); + const fee = this.safeNumber (currency, 'withdrawalFee'); + const precision = this.safeNumber (currency, 'scale'); result[code] = { 'id': id, 'info': currency, @@ -304,7 +305,7 @@ module.exports = class gopax extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawalAmountMin'), + 'min': this.safeNumber (currency, 'withdrawalAmountMin'), 'max': undefined, }, }, @@ -372,8 +373,8 @@ module.exports = class gopax extends Exchange { const marketId = this.safeString (ticker, 'name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (ticker, 'time')); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat2 (ticker, 'price', 'close'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber2 (ticker, 'price', 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -384,20 +385,20 @@ module.exports = class gopax extends Exchange { percentage = change / open * 100; } } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bidVolume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'askVolume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bidVolume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'askVolume'), 'vwap': vwap, 'open': open, 'close': last, @@ -433,14 +434,6 @@ module.exports = class gopax extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTradingPairsStats (params); @@ -462,8 +455,8 @@ module.exports = class gopax extends Exchange { parsePublicTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'time')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'amount'); let symbol = undefined; if ('symbol' in market) { symbol = this.safeString (market, 'symbol'); @@ -489,14 +482,14 @@ module.exports = class gopax extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const symbol = this.safeString (trade, 'tradingPairName').replace ('-', '/'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'baseAmount'); + const price = this.safeNumber (trade, 'price'); + const amount = this.safeNumber (trade, 'baseAmount'); let feeCurrency = symbol.slice (0, 3); if (side === 'sell') { feeCurrency = symbol.slice (4); } const fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': feeCurrency, 'rate': undefined, }; @@ -578,15 +571,15 @@ module.exports = class gopax extends Exchange { } else if (type === '2') { type = 'market'; } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'baseAmount'); - let cost = this.safeFloat (trade, 'quoteAmount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'baseAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteAmount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -653,11 +646,11 @@ module.exports = class gopax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -697,14 +690,14 @@ module.exports = class gopax extends Exchange { const balance = response[i]; const currencyId = this.safeString2 (balance, 'asset', 'isoAlpha3'); const code = this.safeCurrencyCode (currencyId); - const hold = this.safeFloat (balance, 'hold'); - const pendingWithdrawal = this.safeFloat (balance, 'pendingWithdrawal'); + const hold = this.safeString (balance, 'hold'); + const pendingWithdrawal = this.safeString (balance, 'pendingWithdrawal'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.sum (hold, pendingWithdrawal); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = Precise.stringAdd (hold, pendingWithdrawal); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchBalance (params = {}) { @@ -781,42 +774,36 @@ module.exports = class gopax extends Exchange { const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); const timeInForce = this.safeStringUpper (order, 'timeInForce'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const stopPrice = this.safeFloat (order, 'stopPrice'); - const remaining = this.safeFloat (order, 'remaining'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const stopPrice = this.safeNumber (order, 'stopPrice'); + const remaining = this.safeNumber (order, 'remaining'); const marketId = this.safeString (order, 'tradingPairName'); market = this.safeMarket (marketId, market, '-'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const balanceChange = this.safeValue (order, 'balanceChange', {}); - let filled = this.safeFloat (balanceChange, 'baseNet'); - let cost = this.safeFloat (balanceChange, 'quoteNet'); + const filled = this.safeNumber (balanceChange, 'baseNet'); + let cost = this.safeNumber (balanceChange, 'quoteNet'); if (cost !== undefined) { cost = Math.abs (cost); } let updated = undefined; - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } if ((filled !== undefined) && (filled > 0)) { updated = this.parse8601 (this.safeString (order, 'updatedAt')); } - if ((cost === undefined) && (price !== undefined) && (filled !== undefined)) { - cost = filled * price; - } let fee = undefined; if (side === 'buy') { const baseFee = this.safeValue (balanceChange, 'baseFee', {}); - const taking = this.safeFloat (baseFee, 'taking'); - const making = this.safeFloat (baseFee, 'making'); + const taking = this.safeNumber (baseFee, 'taking'); + const making = this.safeNumber (baseFee, 'making'); fee = { 'currency': market['base'], 'cost': this.sum (taking, making), }; } else { const quoteFee = this.safeValue (balanceChange, 'quoteFee', {}); - const taking = this.safeFloat (quoteFee, 'taking'); - const making = this.safeFloat (quoteFee, 'making'); + const taking = this.safeNumber (quoteFee, 'taking'); + const making = this.safeNumber (quoteFee, 'making'); fee = { 'currency': market['quote'], 'cost': this.sum (taking, making), @@ -826,7 +813,7 @@ module.exports = class gopax extends Exchange { if (timeInForce !== undefined) { postOnly = (timeInForce === 'PO'); } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'datetime': this.iso8601 (timestamp), @@ -848,7 +835,7 @@ module.exports = class gopax extends Exchange { 'trades': undefined, 'fee': fee, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -996,7 +983,7 @@ module.exports = class gopax extends Exchange { request['clientOrderId'] = clientOrderId; params = this.omit (params, 'clientOrderId'); } - const stopPrice = this.safeFloat (params, 'stopPrice'); + const stopPrice = this.safeNumber (params, 'stopPrice'); if (stopPrice !== undefined) { request['stopPrice'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, 'stopPrice'); @@ -1125,18 +1112,6 @@ module.exports = class gopax extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetCryptoDepositAddresses (params); @@ -1201,8 +1176,8 @@ module.exports = class gopax extends Exchange { } else if ((type === 'crypto_deposit' || type === 'fiat_deposit')) { type = 'deposit'; } - const amount = this.safeFloat (transaction, 'netAmount'); - const feeCost = this.safeFloat (transaction, 'feeAmount'); + const amount = this.safeNumber (transaction, 'netAmount'); + const feeCost = this.safeNumber (transaction, 'feeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hbtc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hbtc.js index d819c3d77..5dfd98ec5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hbtc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -304,23 +305,23 @@ module.exports = class hbtc extends Exchange { const filter = filters[j]; const filterType = this.safeString (filter, 'filterType'); if (filterType === 'LOT_SIZE') { - amountMin = this.safeFloat (filter, 'minQty'); - amountMax = this.safeFloat (filter, 'maxQty'); + amountMin = this.safeNumber (filter, 'minQty'); + amountMax = this.safeNumber (filter, 'maxQty'); } if (filterType === 'PRICE_FILTER') { - priceMin = this.safeFloat (filter, 'minPrice'); - priceMax = this.safeFloat (filter, 'maxPrice'); + priceMin = this.safeNumber (filter, 'minPrice'); + priceMax = this.safeNumber (filter, 'maxPrice'); } if (filterType === 'MIN_NOTIONAL') { - costMin = this.safeFloat (filter, 'minNotional'); + costMin = this.safeNumber (filter, 'minNotional'); } } if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) { costMin = amountMin * priceMin; } const precision = { - 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'), - 'amount': this.safeFloat (market, 'baseAssetPrecision'), + 'price': this.safeNumber2 (market, 'quotePrecision', 'quoteAssetPrecision'), + 'amount': this.safeNumber (market, 'baseAssetPrecision'), }; const limits = { 'amount': { @@ -558,14 +559,6 @@ module.exports = class hbtc extends Exchange { return this.parseTicker (response, market); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchBidAsk (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -717,8 +710,8 @@ module.exports = class hbtc extends Exchange { const currencyId = this.safeString2 (balance, 'asset', 'tokenName'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'free'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'free'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } } else { @@ -728,12 +721,12 @@ module.exports = class hbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = response[currencyId]; const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableMargin'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'availableMargin'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTrades (symbol, since = undefined, limit = 50, params = {}) { @@ -774,11 +767,11 @@ module.exports = class hbtc extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -1464,8 +1457,8 @@ module.exports = class hbtc extends Exchange { // const currencyId = this.safeString (item, 'tokenId'); const code = this.safeCurrencyCode (currencyId, currency); - const amount = this.safeFloat (item, 'change'); - const after = this.safeFloat (item, 'total'); + const amount = this.safeNumber (item, 'change'); + const after = this.safeNumber (item, 'total'); const direction = (amount < 0) ? 'out' : 'in'; let before = undefined; if (after !== undefined && amount !== undefined) { @@ -1605,8 +1598,8 @@ module.exports = class hbtc extends Exchange { } else { type = 'withdrawal'; } - const amount = this.safeFloat (transaction, 'quantity'); - const feeCost = this.safeFloat (transaction, 'fee'); + const amount = this.safeNumber (transaction, 'quantity'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'feeTokenId'); @@ -1667,8 +1660,8 @@ module.exports = class hbtc extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'openPrice'); - const close = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'openPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); let change = undefined; let percentage = undefined; let average = undefined; @@ -1679,19 +1672,19 @@ module.exports = class hbtc extends Exchange { percentage = (change / open) * 100; } } - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPrice'), - 'low': this.safeFloat (ticker, 'lowPrice'), - 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'), - 'bidVolume': this.safeFloat (ticker, 'bidQty'), - 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'), - 'askVolume': this.safeFloat (ticker, 'askQty'), + 'high': this.safeNumber (ticker, 'highPrice'), + 'low': this.safeNumber (ticker, 'lowPrice'), + 'bid': this.safeNumber2 (ticker, 'bestBidPrice', 'bidPrice'), + 'bidVolume': this.safeNumber (ticker, 'bidQty'), + 'ask': this.safeNumber2 (ticker, 'bestAskPrice', 'askPrice'), + 'askVolume': this.safeNumber (ticker, 'askQty'), 'vwap': vwap, 'open': open, 'close': close, @@ -1741,17 +1734,14 @@ module.exports = class hbtc extends Exchange { // } // const id = this.safeString (trade, 'id'); - const timestamp = this.safeFloat (trade, 'time'); + const timestamp = this.safeNumber (trade, 'time'); const type = undefined; const orderId = this.safeString (trade, 'orderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'qty'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'qty'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let side = undefined; let takerOrMaker = undefined; if ('isBuyerMaker' in trade) { @@ -1765,7 +1755,7 @@ module.exports = class hbtc extends Exchange { side = isBuyer ? 'buy' : 'sell'; } let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionAsset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1871,30 +1861,30 @@ module.exports = class hbtc extends Exchange { const symbol = this.safeSymbol (marketId, market); let type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); - let price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'avgPrice'); + let price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'avgPrice'); let amount = undefined; - let cost = this.safeFloat (order, 'cummulativeQuoteQty'); + let cost = this.safeNumber (order, 'cummulativeQuoteQty'); let filled = undefined; let remaining = undefined; if (type === undefined) { type = this.safeStringLower (order, 'orderType'); if ((market !== undefined) && market['inverse']) { - cost = this.safeFloat (order, 'executedQty'); + cost = this.safeNumber (order, 'executedQty'); amount = undefined; } if (cost === 0.0) { filled = 0; } } else { - amount = this.safeFloat (order, 'origQty'); + amount = this.safeNumber (order, 'origQty'); if (type === 'market') { price = undefined; if (side === 'buy') { amount = undefined; } } - filled = this.safeFloat (order, 'executedQty'); + filled = this.safeNumber (order, 'executedQty'); if (filled !== undefined) { if (amount !== undefined) { remaining = amount - filled; @@ -1906,7 +1896,7 @@ module.exports = class hbtc extends Exchange { } const status = this.parseOrderStatus (this.safeString (order, 'status')); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const result = { 'info': order, 'id': id, @@ -1935,7 +1925,7 @@ module.exports = class hbtc extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'fee'); + const feeCost = this.safeNumber (fees[i], 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'feeToken'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hitbtc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hitbtc.js index b66392816..b7fd38b04 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hitbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hitbtc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, PermissionDenied, ExchangeError, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, RequestTimeout, AuthenticationError } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -44,6 +45,7 @@ module.exports = class hitbtc extends Exchange { 'fetchTransactions': true, 'fetchWithdrawals': false, 'withdraw': true, + 'transfer': true, }, 'timeframes': { '1m': 'M1', @@ -81,10 +83,10 @@ module.exports = class hitbtc extends Exchange { 'api': { 'public': { 'get': [ - 'symbol', // Available Currency Symbols - 'symbol/{symbol}', // Get symbol info 'currency', // Available Currencies 'currency/{currency}', // Get currency info + 'symbol', // Available Currency Symbols + 'symbol/{symbol}', // Get symbol info 'ticker', // Ticker list for all symbols 'ticker/{symbol}', // Ticker for symbol 'trades', @@ -102,11 +104,20 @@ module.exports = class hitbtc extends Exchange { 'order/{clientOrderId}', // Get a single order by clientOrderId 'trading/fee/all', // Get trading fee rate 'trading/fee/{symbol}', // Get trading fee rate + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', 'history/order', // Get historical orders 'history/trades', // Get historical trades 'history/order/{orderId}/trades', // Get historical trades by specified order 'account/balance', // Get main acccount balance - 'account/crypto/address/{currency}', // Get deposit crypro address + 'account/crypto/address/{currency}', // Get current address + 'account/crypto/addresses/{currency}', // Get last 10 deposit addresses for currency + 'account/crypto/used-addresses/{currency}', // Get last 10 unique addresses used for withdraw by currency + 'account/crypto/estimate-withdraw', 'account/crypto/is-mine/{address}', 'account/transactions', // Get account transactions 'account/transactions/{id}', // Get account transaction by id @@ -117,23 +128,33 @@ module.exports = class hitbtc extends Exchange { ], 'post': [ 'order', // Create new order - 'account/crypto/address/{currency}', // Create new deposit crypro address - 'account/crypto/withdraw', // Withdraw crypro + 'margin/order', + 'account/crypto/address/{currency}', // Create new crypto deposit address + 'account/crypto/withdraw', // Withdraw crypto 'account/crypto/transfer-convert', - 'account/transfer', // Transfer amount to trading + 'account/transfer', // Transfer amount to trading account or to main account + 'account/transfer/internal', 'sub-acc/freeze', 'sub-acc/activate', 'sub-acc/transfer', ], 'put': [ 'order/{clientOrderId}', // Create new order - 'account/crypto/withdraw/{id}', // Commit withdraw crypro + 'margin/account/{symbol}', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Commit crypto withdrawal 'sub-acc/acl/{subAccountUserId}', ], 'delete': [ 'order', // Cancel all open orders 'order/{clientOrderId}', // Cancel order - 'account/crypto/withdraw/{id}', // Rollback withdraw crypro + 'margin/account', + 'margin/account/{symbol}', + 'margin/position', + 'margin/position/{symbol}', + 'margin/order', + 'margin/order/{clientOrderId}', + 'account/crypto/withdraw/{id}', // Rollback crypto withdrawal ], // outdated? 'patch': [ @@ -152,8 +173,20 @@ module.exports = class hitbtc extends Exchange { }, 'options': { 'defaultTimeInForce': 'FOK', + 'accountsByType': { + 'bank': 'bank', + 'exchange': 'exchange', + 'main': 'bank', // alias of the above + 'trading': 'exchange', + }, + 'fetchBalanceMethod': { + 'account': 'account', + 'main': 'account', + 'trading': 'trading', + }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive 'BET': 'DAO.Casino', 'BOX': 'BOX Token', @@ -180,7 +213,6 @@ module.exports = class hitbtc extends Exchange { '20002': OrderNotFound, // canceling non-existent order '20001': InsufficientFunds, // {"error":{"code":20001,"message":"Insufficient funds","description":"Check that the funds are sufficient, given commissions"}} }, - 'orders': {}, // orders cache / emulation }); } @@ -217,14 +249,14 @@ module.exports = class hitbtc extends Exchange { if (id.indexOf ('_') >= 0) { symbol = id; } - const lot = this.safeFloat (market, 'quantityIncrement'); - const step = this.safeFloat (market, 'tickSize'); + const lot = this.safeNumber (market, 'quantityIncrement'); + const step = this.safeNumber (market, 'tickSize'); const precision = { 'price': step, 'amount': lot, }; - const taker = this.safeFloat (market, 'takeLiquidityRate'); - const maker = this.safeFloat (market, 'provideLiquidityRate'); + const taker = this.safeNumber (market, 'takeLiquidityRate'); + const maker = this.safeNumber (market, 'provideLiquidityRate'); const feeCurrencyId = this.safeString (market, 'feeCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); result.push (this.extend (this.fees['trading'], { @@ -259,6 +291,49 @@ module.exports = class hitbtc extends Exchange { return result; } + async transfer (code, amount, fromAccount, toAccount, params = {}) { + // account can be "exchange" or "bank", with aliases "main" or "trading" respectively + await this.loadMarkets (); + const currency = this.currency (code); + const requestAmount = this.currencyToPrecision (code, amount); + const request = { + 'currency': currency['id'], + 'amount': requestAmount, + }; + let type = this.safeString (params, 'type'); + if (type === undefined) { + const accountsByType = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsByType, fromAccount); + const toId = this.safeString (accountsByType, toAccount); + const keys = Object.keys (accountsByType); + if (fromId === undefined) { + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ') + ' instead of ' + fromId); + } + if (toId === undefined) { + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ') + ' instead of ' + toId); + } + if (fromId === toId) { + throw new ExchangeError (this.id + ' from and to cannot be the same account'); + } + type = fromId + 'To' + this.capitalize (toId); + } + request['type'] = type; + const response = await this.privatePostAccountTransfer (this.extend (request, params)); + // { id: '2db6ebab-fb26-4537-9ef8-1a689472d236' } + const id = this.safeString (response, 'id'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'amount': requestAmount, + 'currency': code, + 'fromAccount': fromAccount, + 'toAccount': toAccount, + 'status': undefined, + }; + } + async fetchCurrencies (params = {}) { const response = await this.publicGetCurrency (params); // @@ -314,7 +389,7 @@ module.exports = class hitbtc extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (currency, 'payoutFee'), // todo: redesign + 'fee': this.safeNumber (currency, 'payoutFee'), // todo: redesign 'precision': precision, 'limits': { 'amount': { @@ -354,15 +429,20 @@ module.exports = class hitbtc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } async fetchBalance (params = {}) { await this.loadMarkets (); const type = this.safeString (params, 'type', 'trading'); - const method = 'privateGet' + this.capitalize (type) + 'Balance'; + const fetchBalanceAccounts = this.safeValue (this.options, 'fetchBalanceMethod', {}); + const typeId = this.safeString (fetchBalanceAccounts, type); + if (typeId === undefined) { + throw new ExchangeError (this.id + ' fetchBalance account type must be either main or trading'); + } + const method = 'privateGet' + this.capitalize (typeId) + 'Balance'; const query = this.omit (params, 'type'); const response = await this[method] (query); const result = { 'info': response }; @@ -371,11 +451,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'reserved'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -392,11 +472,11 @@ module.exports = class hitbtc extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'max'), - this.safeFloat (ohlcv, 'min'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'max'), + this.safeNumber (ohlcv, 'min'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -442,10 +522,10 @@ module.exports = class hitbtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const baseVolume = this.safeFloat (ticker, 'volume'); - const quoteVolume = this.safeFloat (ticker, 'volumeQuote'); - const open = this.safeFloat (ticker, 'open'); - const last = this.safeFloat (ticker, 'last'); + const baseVolume = this.safeNumber (ticker, 'volume'); + const quoteVolume = this.safeNumber (ticker, 'volumeQuote'); + const open = this.safeNumber (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); let change = undefined; let percentage = undefined; let average = undefined; @@ -461,11 +541,11 @@ module.exports = class hitbtc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -541,7 +621,7 @@ module.exports = class hitbtc extends Exchange { market = this.safeMarket (marketId, market); const symbol = market['symbol']; let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyCode = market ? market['feeCurrency'] : undefined; fee = { @@ -553,9 +633,11 @@ module.exports = class hitbtc extends Exchange { // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const orderId = this.safeString (trade, 'clientOrderId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = price * amount; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); const id = this.safeString (trade, 'id'); return { @@ -654,11 +736,11 @@ module.exports = class hitbtc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const txid = this.safeString (transaction, 'hash'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -846,66 +928,25 @@ module.exports = class hitbtc extends Exchange { const marketId = this.safeString (order, 'symbol'); market = this.safeMarket (marketId, market); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'cumQuantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'cumQuantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); // we use clientOrderId as the order id with this exchange intentionally // because most of their endpoints will require clientOrderId // explained here: https://github.com/ccxt/ccxt/issues/5674 const id = this.safeString (order, 'clientOrderId'); const clientOrderId = id; - let price = this.safeFloat (order, 'price'); - let remaining = undefined; - let cost = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - if (price !== undefined) { - cost = filled * price; - } - } - } + const price = this.safeNumber (order, 'price'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); let trades = this.safeValue (order, 'tradesReport'); - let fee = undefined; - let average = this.safeValue (order, 'avgPrice'); + const fee = undefined; + const average = this.safeNumber (order, 'avgPrice'); if (trades !== undefined) { trades = this.parseTrades (trades, market); - let feeCost = undefined; - const numTrades = trades.length; - let tradesCost = 0; - for (let i = 0; i < numTrades; i++) { - if (feeCost === undefined) { - feeCost = 0; - } - tradesCost = this.sum (tradesCost, trades[i]['cost']); - const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); - if (tradeFeeCost !== undefined) { - feeCost = this.sum (feeCost, tradeFeeCost); - } - } - cost = tradesCost; - if ((filled !== undefined) && (filled > 0)) { - if (average === undefined) { - average = cost / filled; - } - if (type === 'market') { - if (price === undefined) { - price = average; - } - } - } - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } } const timeInForce = this.safeString (order, 'timeInForce'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, // https://github.com/ccxt/ccxt/issues/5674 'timestamp': created, @@ -920,13 +961,13 @@ module.exports = class hitbtc extends Exchange { 'stopPrice': undefined, 'average': average, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hollaex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hollaex.js index 52e81fec3..bde50ed15 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hollaex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/hollaex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadRequest, AuthenticationError, NetworkError, ArgumentsRequired, OrderNotFound, InsufficientFunds } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -15,7 +16,7 @@ module.exports = class hollaex extends Exchange { 'name': 'HollaEx', 'countries': [ 'KR' ], 'rateLimit': 333, - 'version': 'v1', + 'version': 'v2', 'has': { 'CORS': false, 'fetchMarkets': true, @@ -35,13 +36,13 @@ module.exports = class hollaex extends Exchange { 'cancelOrder': true, 'cancelAllOrders': true, 'fetchOpenOrders': true, - 'fetchClosedOrders': false, + 'fetchClosedOrders': true, 'fetchOpenOrder': true, 'fetchOrder': false, 'fetchDeposits': true, 'fetchWithdrawals': true, 'fetchTransactions': false, - 'fetchOrders': false, + 'fetchOrders': true, 'fetchMyTrades': true, 'withdraw': true, 'fetchDepositAddress': true, @@ -66,13 +67,17 @@ module.exports = class hollaex extends Exchange { 'public': { 'get': [ 'health', - 'constant', + 'constants', + 'kit', + 'tiers', 'ticker', - 'ticker/all', + 'tickers', + 'orderbook', 'orderbooks', 'trades', 'chart', - // TradingView data + 'charts', + // TradingView 'udf/config', 'udf/history', 'udf/symbols', @@ -82,20 +87,20 @@ module.exports = class hollaex extends Exchange { 'get': [ 'user', 'user/balance', - 'user/trades', - 'user/orders', - 'user/orders/{order_id}', 'user/deposits', 'user/withdrawals', - 'user/withdraw/{currency}/fee', + 'user/withdrawal/fee', + 'user/trades', + 'orders', + 'orders/{order_id}', ], 'post': [ 'user/request-withdrawal', 'order', ], 'delete': [ - 'user/orders', - 'user/orders/{order_id}', + 'order/all', + 'order', ], }, }, @@ -130,7 +135,7 @@ module.exports = class hollaex extends Exchange { } async fetchMarkets (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); // // { // coins: { @@ -197,17 +202,17 @@ module.exports = class hollaex extends Exchange { 'quoteId': quoteId, 'active': active, 'precision': { - 'price': this.safeFloat (market, 'increment_price'), - 'amount': this.safeFloat (market, 'increment_size'), + 'price': this.safeNumber (market, 'increment_price'), + 'amount': this.safeNumber (market, 'increment_size'), }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_size'), - 'max': this.safeFloat (market, 'max_size'), + 'min': this.safeNumber (market, 'min_size'), + 'max': this.safeNumber (market, 'max_size'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, 'max': undefined }, }, @@ -218,7 +223,7 @@ module.exports = class hollaex extends Exchange { } async fetchCurrencies (params = {}) { - const response = await this.publicGetConstant (params); + const response = await this.publicGetConstants (params); const coins = this.safeValue (response, 'coins', {}); const keys = Object.keys (coins); const result = {}; @@ -230,8 +235,8 @@ module.exports = class hollaex extends Exchange { const code = this.safeCurrencyCode (id); const name = this.safeString (currency, 'fullname'); const active = this.safeValue (currency, 'active'); - const fee = this.safeFloat (currency, 'withdrawal_fee'); - const precision = this.safeFloat (currency, 'increment_unit'); + const fee = this.safeNumber (currency, 'withdrawal_fee'); + const precision = this.safeNumber (currency, 'increment_unit'); const withdrawalLimits = this.safeValue (currency, 'withdrawal_limits', []); result[code] = { 'id': id, @@ -244,8 +249,8 @@ module.exports = class hollaex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'min'), - 'max': this.safeFloat (currency, 'max'), + 'min': this.safeNumber (currency, 'min'), + 'max': this.safeNumber (currency, 'max'), }, 'price': { 'min': undefined, @@ -334,7 +339,7 @@ module.exports = class hollaex extends Exchange { async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); - const response = await this.publicGetTickerAll (this.extend (params)); + const response = await this.publicGetTickers (this.extend (params)); // // { // "bch-usdt": { @@ -397,27 +402,27 @@ module.exports = class hollaex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString2 (ticker, 'time', 'timestamp')); - const close = this.safeFloat (ticker, 'close'); + const close = this.safeNumber (ticker, 'close'); const result = { 'symbol': symbol, 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': close, - 'last': this.safeFloat (ticker, 'last', close), + 'last': this.safeNumber (ticker, 'last', close), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, }; return result; @@ -475,15 +480,12 @@ module.exports = class hollaex extends Exchange { const datetime = this.safeString (trade, 'timestamp'); const timestamp = this.parse8601 (datetime); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'size'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'size'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const quote = market['quote']; @@ -568,11 +570,11 @@ module.exports = class hollaex extends Exchange { // return [ this.parse8601 (this.safeString (response, 'time')), - this.safeFloat (response, 'open'), - this.safeFloat (response, 'high'), - this.safeFloat (response, 'low'), - this.safeFloat (response, 'close'), - this.safeFloat (response, 'volume'), + this.safeNumber (response, 'open'), + this.safeNumber (response, 'high'), + this.safeNumber (response, 'low'), + this.safeNumber (response, 'close'), + this.safeNumber (response, 'volume'), ]; } @@ -597,11 +599,11 @@ module.exports = class hollaex extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (response, currencyId + '_available'); - account['total'] = this.safeFloat (response, currencyId + '_balance'); + account['free'] = this.safeString (response, currencyId + '_available'); + account['total'] = this.safeString (response, currencyId + '_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOpenOrder (id, symbol = undefined, params = {}) { @@ -609,67 +611,146 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateGetUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateGetOrdersOrderId (this.extend (request, params)); // // { - // "created_at": "2018-03-23T04:14:08.663Z", - // "title": "string", - // "side": "sell", - // "type": "limit", - // "price": 0, - // "size": 0, - // "symbol": "xht-usdt", // "id": "string", - // "created_by": 1, - // "filled": 0 + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } // } // return this.parseOrder (response); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'open': true, + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + const request = { + 'status': 'filled', + }; + return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); + } + + async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = undefined; - const request = {}; + const request = { + // 'symbol': market['id'], + // 'side': 'buy', // 'sell' + // 'status': 'new', // 'filled', 'pfilled', 'canceled' + // 'open': true, + // 'limit': limit, // default 50, max 100 + // 'page': 1, + // 'order_by': 'created_at', // id, ... + // 'order': 'asc', // 'desc' + // 'start_date': this.iso8601 (since), + // 'end_date': this.iso8601 (this.milliseconds ()), + }; if (symbol !== undefined) { market = this.market (symbol); request['symbol'] = market['id']; } - const response = await this.privateGetUserOrders (this.extend (request, params)); + if (since !== undefined) { + request['start_date'] = this.iso8601 (since); + } + if (limit !== undefined) { + request['limit'] = limit; // default 50, max 100 + } + const response = await this.privateGetOrders (this.extend (request, params)); // - // [ - // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 - // } - // ] + // { + // "count": 1, + // "data": [ + // { + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // } + // } + // ] + // } // - return this.parseOrders (response, market); + const data = this.safeValue (response, 'data', []); + return this.parseOrders (data, market, since, limit); + } + + parseOrderStatus (status) { + const statuses = { + 'new': 'open', + 'pfilled': 'open', + 'filled': 'closed', + 'canceled': 'canceled', + }; + return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // - // fetchOpenOrder, fetchOpenOrders + // createOrder, fetchOpenOrder, fetchOpenOrders // // { - // "created_at":"2020-03-03T08:02:18.639Z", - // "title":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "side":"buy", - // "type":"limit", - // "price":226.19, - // "size":0.086, - // "symbol":"eth-usdt", - // "id":"5419ff3f-9d25-4af7-bcc2-803926518d76", - // "created_by":620, - // "filled":0 + // "id": "string", + // "side": "sell", + // "symbol": "xht-usdt", + // "size": 0.1, + // "filled": 0, + // "stop": null, + // "fee": 0, + // "fee_coin": "usdt", + // "type": "limit", + // "price": 1.09, + // "status": "new", + // "created_by": 116, + // "created_at": "2021-02-17T02:32:38.910Z", + // "updated_at": "2021-02-17T02:32:38.910Z", + // "User": { + // "id": 116, + // "email": "fight@club.com", + // "username": "narrator", + // "exchange_id": 176 + // }, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, // } // const marketId = this.safeString (order, 'symbol'); @@ -678,21 +759,11 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'filled'); - let cost = undefined; - let remaining = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (price !== undefined) { - cost = filled * price; - } - } - const status = (type === 'market') ? 'closed' : 'open'; - const result = { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'filled'); + const status = this.parseOrderStatus (this.safeString (order, 'status')); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -708,40 +779,56 @@ module.exports = class hollaex extends Exchange { 'stopPrice': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, - 'cost': cost, + 'remaining': undefined, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': undefined, - }; - return result; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); - const order = { + const request = { 'symbol': market['id'], 'side': side, 'size': amount, 'type': type, + // 'stop': parseFloat (this.priceToPrecision (symbol, stopPrice)), + // 'meta': {}, // other options such as post_only }; if (type !== 'market') { - order['price'] = price; + request['price'] = price; } - const response = await this.privatePostOrder (this.extend (order, params)); + const stopPrice = this.safeFloat2 (params, 'stopPrice', 'stop'); + if (stopPrice !== undefined) { + request['stop'] = parseFloat (this.priceToPrecision (symbol, stopPrice)); + params = this.omit (params, [ 'stopPrice', 'stop' ]); + } + const response = await this.privatePostOrder (this.extend (request, params)); // // { + // "fee": 0, + // "meta": {}, // "symbol": "xht-usdt", // "side": "sell", - // "size": 1, + // "size": 0.1, // "type": "limit", - // "price": 0.1, + // "price": 1, + // "fee_structure": { + // "maker": 0.2, + // "taker": 0.2 + // }, + // "fee_coin": "usdt", // "id": "string", - // "created_by": 34, + // "created_by": 116, // "filled": 0, - // "status": "pending" + // "status": "new", + // "updated_at": "2021-02-17T03:03:19.231Z", + // "created_at": "2021-02-17T03:03:19.231Z", + // "stop": null // } // return this.parseOrder (response, market); @@ -752,7 +839,7 @@ module.exports = class hollaex extends Exchange { const request = { 'order_id': id, }; - const response = await this.privateDeleteUserOrdersOrderId (this.extend (request, params)); + const response = await this.privateDeleteOrder (this.extend (request, params)); // // { // "title": "string", @@ -777,7 +864,7 @@ module.exports = class hollaex extends Exchange { market = this.markets (symbol); request['symbol'] = market['id']; } - const response = await this.privateDeleteUserOrders (this.extend (request, params)); + const response = await this.privateDeleteOrderAll (this.extend (request, params)); // // [ // { @@ -1043,7 +1130,7 @@ module.exports = class hollaex extends Exchange { const timestamp = this.parse8601 (this.safeString (transaction, 'created_at')); const updated = this.parse8601 (this.safeString (transaction, 'updated_at')); const type = this.safeString (transaction, 'type'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let address = this.safeString (transaction, 'address'); let addressTo = undefined; const addressFrom = undefined; @@ -1073,7 +1160,7 @@ module.exports = class hollaex extends Exchange { } const fee = { 'currency': code, - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), }; return { 'info': transaction, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/huobipro.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/huobipro.js index 52dc315e8..22c1d91d5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/huobipro.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/huobipro.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, ExchangeNotAvailable, OnMaintenance, InvalidOrder, OrderNotFound, InsufficientFunds, ArgumentsRequired, BadSymbol, BadRequest, RequestTimeout, NetworkError } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -22,7 +23,9 @@ module.exports = class huobipro extends Exchange { 'hostname': 'api.huobi.pro', // api.testnet.huobi.pro 'pro': true, 'has': { + 'cancelAllOrders': true, 'cancelOrder': true, + 'cancelOrders': true, 'CORS': false, 'createOrder': true, 'fetchBalance': true, @@ -189,6 +192,7 @@ module.exports = class huobipro extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.002, @@ -252,6 +256,7 @@ module.exports = class huobipro extends Exchange { // https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/ 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', + 'BIFI': 'Bitcoin File', // conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706 }, }); } @@ -316,8 +321,8 @@ module.exports = class huobipro extends Exchange { 'info': limits, 'limits': { 'amount': { - 'min': this.safeFloat (limits, 'limit-order-must-greater-than'), - 'max': this.safeFloat (limits, 'limit-order-must-less-than'), + 'min': this.safeNumber (limits, 'limit-order-must-greater-than'), + 'max': this.safeNumber (limits, 'limit-order-must-less-than'), }, }, }; @@ -351,9 +356,9 @@ module.exports = class huobipro extends Exchange { }; const maker = (base === 'OMG') ? 0 : 0.2 / 100; const taker = (base === 'OMG') ? 0 : 0.2 / 100; - const minAmount = this.safeFloat (market, 'min-order-amt', Math.pow (10, -precision['amount'])); - const maxAmount = this.safeFloat (market, 'max-order-amt'); - const minCost = this.safeFloat (market, 'min-order-value', 0); + const minAmount = this.safeNumber (market, 'min-order-amt', Math.pow (10, -precision['amount'])); + const maxAmount = this.safeNumber (market, 'max-order-amt'); + const minCost = this.safeNumber (market, 'min-order-value', 0); const state = this.safeString (market, 'state'); const active = (state === 'online'); result.push ({ @@ -432,24 +437,24 @@ module.exports = class huobipro extends Exchange { let askVolume = undefined; if ('bid' in ticker) { if (Array.isArray (ticker['bid'])) { - bid = this.safeFloat (ticker['bid'], 0); - bidVolume = this.safeFloat (ticker['bid'], 1); + bid = this.safeNumber (ticker['bid'], 0); + bidVolume = this.safeNumber (ticker['bid'], 1); } else { - bid = this.safeFloat (ticker, 'bid'); + bid = this.safeNumber (ticker, 'bid'); bidVolume = this.safeValue (ticker, 'bidSize'); } } if ('ask' in ticker) { if (Array.isArray (ticker['ask'])) { - ask = this.safeFloat (ticker['ask'], 0); - askVolume = this.safeFloat (ticker['ask'], 1); + ask = this.safeNumber (ticker['ask'], 0); + askVolume = this.safeNumber (ticker['ask'], 1); } else { - ask = this.safeFloat (ticker, 'ask'); + ask = this.safeNumber (ticker, 'ask'); askVolume = this.safeValue (ticker, 'askSize'); } } - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; let percentage = undefined; let average = undefined; @@ -460,15 +465,15 @@ module.exports = class huobipro extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'amount'); - const quoteVolume = this.safeFloat (ticker, 'vol'); + const baseVolume = this.safeNumber (ticker, 'amount'); + const quoteVolume = this.safeNumber (ticker, 'vol'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': bid, 'bidVolume': bidVolume, 'ask': ask, @@ -557,7 +562,7 @@ module.exports = class huobipro extends Exchange { // } // const ticker = this.parseTicker (response['tick'], market); - const timestamp = this.safeValue (response, 'ts'); + const timestamp = this.safeInteger (response, 'ts'); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601 (timestamp); return ticker; @@ -626,21 +631,18 @@ module.exports = class huobipro extends Exchange { type = typeParts[1]; } const takerOrMaker = this.safeString (trade, 'role'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'filled-amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'filled-amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - let feeCost = this.safeFloat (trade, 'filled-fees'); + let feeCost = this.safeNumber (trade, 'filled-fees'); let feeCurrency = undefined; if (market !== undefined) { feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'fee-currency')); } - const filledPoints = this.safeFloat (trade, 'filled-points'); + const filledPoints = this.safeNumber (trade, 'filled-points'); if (filledPoints !== undefined) { if ((feeCost === undefined) || (feeCost === 0.0)) { feeCost = filledPoints; @@ -754,11 +756,11 @@ module.exports = class huobipro extends Exchange { // return [ this.safeTimestamp (ohlcv, 'id'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'amount'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'amount'), ]; } @@ -855,11 +857,11 @@ module.exports = class huobipro extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'deposit-min-amount'), + 'min': this.safeNumber (currency, 'deposit-min-amount'), 'max': Math.pow (10, precision), }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdraw-min-amount'), + 'min': this.safeNumber (currency, 'withdraw-min-amount'), 'max': Math.pow (10, precision), }, }, @@ -890,14 +892,14 @@ module.exports = class huobipro extends Exchange { account = this.account (); } if (balance['type'] === 'trade') { - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); } if (balance['type'] === 'frozen') { - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); } result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrdersByStates (states, symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1072,28 +1074,14 @@ module.exports = class huobipro extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeInteger (order, 'created-at'); - let amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount - if ((type === 'market') && (side === 'buy')) { - amount = (status === 'closed') ? filled : undefined; - } - let price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber2 (order, 'filled-amount', 'field-amount'); // typo in their API, filled amount + let price = this.safeNumber (order, 'price'); if (price === 0.0) { price = undefined; } - const cost = this.safeFloat2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - // if cost is defined and filled is not zero - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - const feeCost = this.safeFloat2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees + const cost = this.safeNumber2 (order, 'filled-cash-amount', 'field-cash-amount'); // same typo + const feeCost = this.safeNumber2 (order, 'filled-fees', 'field-fees'); // typo in their API, filled fees let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -1105,7 +1093,7 @@ module.exports = class huobipro extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -1119,15 +1107,15 @@ module.exports = class huobipro extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1201,26 +1189,82 @@ module.exports = class huobipro extends Exchange { }); } - currencyToPrecision (currency, fee) { - return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); + async cancelOrders (ids, symbol = undefined, params = {}) { + await this.loadMarkets (); + const clientOrderIds = this.safeValue2 (params, 'clientOrderIds', 'client-order-ids'); + params = this.omit (params, [ 'clientOrderIds', 'client-order-ids' ]); + const request = {}; + if (clientOrderIds === undefined) { + request['order-ids'] = ids; + } else { + request['client-order-ids'] = clientOrderIds; + } + const response = await this.privatePostOrderOrdersBatchcancel (this.extend (request, params)); + // + // { + // "status": "ok", + // "data": { + // "success": [ + // "5983466" + // ], + // "failed": [ + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "first" + // }, + // { + // "err-msg": "Incorrect order state", + // "order-state": 7, + // "order-id": "", + // "err-code": "order-orderstate-error", + // "client-order-id": "second" + // }, + // { + // "err-msg": "The record is not found.", + // "order-id": "", + // "err-code": "base-not-found", + // "client-order-id": "third" + // } + // ] + // } + // } + // + return response; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let key = 'quote'; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.currencyToPrecision (market[key], cost)), + async cancelAllOrders (symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + // 'account-id' string false NA The account id used for this cancel Refer to GET /v1/account/accounts + // 'symbol': market['id'], // a list of comma-separated symbols, all symbols by default + // 'types' 'string', buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok + // 'side': 'buy', // or 'sell' + // 'size': 100, // the number of orders to cancel 1-100 }; + let market = undefined; + if (symbol !== undefined) { + market = this.market (symbol); + request['symbol'] = market['id']; + } + const response = await this.privatePostOrderOrdersBatchCancelOpenOrders (this.extend (request, params)); + // + // { + // code: 200, + // data: { + // "success-count": 2, + // "failed-count": 0, + // "next-id": 5454600 + // } + // } + // + return response; + } + + currencyToPrecision (currency, fee) { + return this.decimalToPrecision (fee, 0, this.currencies[currency]['precision']); } parseDepositAddress (depositAddress, currency = undefined) { @@ -1362,7 +1406,7 @@ module.exports = class huobipro extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); const tag = this.safeString (transaction, 'address-tag'); - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { feeCost = Math.abs (feeCost); } @@ -1375,7 +1419,7 @@ module.exports = class huobipro extends Exchange { 'address': this.safeString (transaction, 'address'), 'tag': tag, 'type': type, - 'amount': this.safeFloat (transaction, 'amount'), + 'amount': this.safeNumber (transaction, 'amount'), 'currency': code, 'status': status, 'updated': updated, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ice3x.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ice3x.js deleted file mode 100644 index f228076d1..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ice3x.js +++ /dev/null @@ -1,495 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); -const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); - -// --------------------------------------------------------------------------- - -module.exports = class ice3x extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'ice3x', - 'name': 'ICE3X', - 'countries': [ 'ZA' ], // South Africa - 'rateLimit': 1000, - 'version': 'v1', - 'has': { - 'cancelOrder': true, - 'createOrder': true, - 'fetchBalance': true, - 'fetchCurrencies': true, - 'fetchDepositAddress': true, - 'fetchMarkets': true, - 'fetchMyTrades': true, - 'fetchOpenOrders': true, - 'fetchOrder': true, - 'fetchOrderBook': true, - 'fetchTicker': true, - 'fetchTickers': true, - 'fetchTrades': true, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/51840849/87460809-1dd06c00-c616-11ea-98ad-7d5e1cb7fcdd.jpg', - 'api': 'https://ice3x.com/api', - 'www': 'https://ice3x.com', // 'https://ice3x.co.za', - 'doc': 'https://ice3x.co.za/ice-cubed-bitcoin-exchange-api-documentation-1-june-2017', - 'fees': [ - 'https://help.ice3.com/support/solutions/articles/11000033293-trading-fees', - 'https://help.ice3.com/support/solutions/articles/11000033288-fees-explained', - 'https://help.ice3.com/support/solutions/articles/11000008131-what-are-your-fiat-deposit-and-withdrawal-fees-', - 'https://help.ice3.com/support/solutions/articles/11000033289-deposit-fees', - ], - 'referral': 'https://ice3x.com?ref=14341802', - }, - 'api': { - 'public': { - 'get': [ - 'currency/list', - 'currency/info', - 'pair/list', - 'pair/info', - 'stats/marketdepthfull', - 'stats/marketdepthbtcav', - 'stats/marketdepth', - 'orderbook/info', - 'trade/list', - 'trade/info', - ], - }, - 'private': { - 'post': [ - 'balance/list', - 'balance/info', - 'order/new', - 'order/cancel', - 'order/list', - 'order/info', - 'trade/list', - 'trade/info', - 'transaction/list', - 'transaction/info', - 'invoice/list', - 'invoice/info', - 'invoice/pdf', - ], - }, - }, - 'fees': { - 'trading': { - 'maker': 0.005, - 'taker': 0.005, - }, - }, - 'precision': { - 'amount': 8, - 'price': 8, - }, - }); - } - - async fetchCurrencies (params = {}) { - const response = await this.publicGetCurrencyList (params); - const currencies = response['response']['entities']; - const precision = this.precision['amount']; - const result = {}; - for (let i = 0; i < currencies.length; i++) { - const currency = currencies[i]; - const id = this.safeString (currency, 'currency_id'); - const currencyId = this.safeString (currency, 'iso'); - const code = this.safeCurrencyCode (currencyId); - result[code] = { - 'id': id, - 'code': code, - 'name': currency['name'], - 'active': true, - 'precision': precision, - 'limits': { - 'amount': { - 'min': undefined, - 'max': Math.pow (10, precision), - }, - 'price': { - 'min': Math.pow (10, -precision), - 'max': Math.pow (10, precision), - }, - 'cost': { - 'min': undefined, - 'max': undefined, - }, - }, - 'info': currency, - 'fee': undefined, - }; - } - return result; - } - - async fetchMarkets (params = {}) { - if (this.currencies_by_id === undefined) { - this.currencies = await this.fetchCurrencies (); - this.currencies_by_id = this.indexBy (this.currencies, 'id'); - } - const response = await this.publicGetPairList (params); - const markets = this.safeValue (response['response'], 'entities'); - const result = []; - for (let i = 0; i < markets.length; i++) { - const market = markets[i]; - const id = this.safeString (market, 'pair_id'); - const baseId = this.safeString (market, 'currency_id_from'); - const quoteId = this.safeString (market, 'currency_id_to'); - const baseCurrency = this.currencies_by_id[baseId]; - const quoteCurrency = this.currencies_by_id[quoteId]; - const base = baseCurrency['code']; - const quote = quoteCurrency['code']; - const symbol = base + '/' + quote; - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'active': undefined, - 'info': market, - 'precision': this.precision, - 'limits': this.limits, - }); - } - return result; - } - - parseTicker (ticker, market = undefined) { - const timestamp = this.milliseconds (); - const symbol = market['symbol']; - const last = this.safeFloat (ticker, 'last_price'); - return { - 'symbol': symbol, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max'), - 'low': this.safeFloat (ticker, 'min'), - 'bid': this.safeFloat (ticker, 'max_bid'), - 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'min_ask'), - 'askVolume': undefined, - 'vwap': undefined, - 'open': undefined, - 'close': last, - 'last': last, - 'previousClose': undefined, - 'change': undefined, - 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'vol'), - 'info': ticker, - }; - } - - async fetchTicker (symbol, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetStatsMarketdepthfull (this.extend (request, params)); - const ticker = this.safeValue (response['response'], 'entity'); - return this.parseTicker (ticker, market); - } - - async fetchTickers (symbols = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetStatsMarketdepthfull (params); - const tickers = this.safeValue (response['response'], 'entities'); - const result = {}; - for (let i = 0; i < tickers.length; i++) { - const ticker = tickers[i]; - const marketId = this.safeString (ticker, 'pair_id'); - const market = this.safeValue (this.marketsById, marketId); - if (market !== undefined) { - const symbol = market['symbol']; - result[symbol] = this.parseTicker (ticker, market); - } - } - return this.filterByArray (result, 'symbol', symbols); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'pair_id': this.marketId (symbol), - }; - if (limit !== undefined) { - const type = this.safeString (params, 'type'); - if ((type !== 'ask') && (type !== 'bid')) { - // eslint-disable-next-line quotes - throw new ArgumentsRequired (this.id + " fetchOrderBook() requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit"); - } else { - request['items_per_page'] = limit; - } - } - const response = await this.publicGetOrderbookInfo (this.extend (request, params)); - const orderbook = this.safeValue (response['response'], 'entities'); - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.safeTimestamp (trade, 'created'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - 'currency': market['quote'], - }; - } - const type = 'limit'; - const side = this.safeString (trade, 'type'); - const id = this.safeString (trade, 'trade_id'); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - return { - 'id': id, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': type, - 'side': side, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': fee, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - const response = await this.publicGetTradeList (this.extend (request, params)); - const trades = this.safeValue (response['response'], 'entities'); - return this.parseTrades (trades, market, since, limit); - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privatePostBalanceList (params); - const result = { 'info': response }; - const balances = this.safeValue (response['response'], 'entities', []); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - // currency ids are numeric strings - const currencyId = this.safeString (balance, 'currency_id'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - result[code] = account; - } - return this.parseBalance (result); - } - - parseOrder (order, market = undefined) { - const pairId = this.safeInteger (order, 'pair_id'); - let symbol = undefined; - if (pairId && !market && (pairId in this.marketsById)) { - market = this.marketsById[pairId]; - symbol = market['symbol']; - } - const timestamp = this.safeTimestamp (order, 'created'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - let status = this.safeInteger (order, 'active'); - let remaining = this.safeFloat (order, 'remaining'); - let filled = undefined; - if (status === 1) { - status = 'open'; - } else { - status = 'closed'; - remaining = 0; - filled = amount; - } - let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); - if (feeCost !== undefined) { - fee = { - 'cost': feeCost, - }; - if (market !== undefined) { - fee['currency'] = market['quote']; - } - } - return { - 'id': this.safeString (order, 'order_id'), - 'clientOrderId': undefined, - 'datetime': this.iso8601 (timestamp), - 'timestamp': timestamp, - 'lastTradeTimestamp': undefined, - 'status': status, - 'symbol': symbol, - 'type': 'limit', - 'timeInForce': undefined, - 'postOnly': undefined, - 'side': this.safeString (order, 'type'), - 'price': price, - 'stopPrice': undefined, - 'cost': undefined, - 'amount': amount, - 'filled': filled, - 'remaining': remaining, - 'trades': undefined, - 'fee': fee, - 'info': order, - 'average': undefined, - }; - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - 'type': side, - 'amount': amount, - 'price': price, - }; - const response = await this.privatePostOrderNew (this.extend (request, params)); - const order = this.parseOrder ({ - 'order_id': response['response']['entity']['order_id'], - 'created': this.seconds (), - 'active': 1, - 'type': side, - 'price': price, - 'volume': amount, - 'remaining': amount, - 'info': response, - }, market); - return order; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - const request = { - 'order_id': id, - }; - return await this.privatePostOrderCancel (this.extend (request, params)); - } - - async fetchOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'order _id': id, - }; - const response = await this.privatePostOrderInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const order = this.safeValue (data, 'entity'); - return this.parseOrder (order); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.privatePostOrderList (params); - const data = this.safeValue (response, 'response', {}); - const orders = this.safeValue (data, 'entities', []); - let market = undefined; - if (symbol !== undefined) { - market = this.market (symbol); - } - return this.parseOrders (orders, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'pair_id': market['id'], - }; - if (limit !== undefined) { - request['items_per_page'] = limit; - } - if (since !== undefined) { - request['date_from'] = parseInt (since / 1000); - } - const response = await this.privatePostTradeList (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const trades = this.safeValue (data, 'entities', []); - return this.parseTrades (trades, market, since, limit); - } - - async fetchDepositAddress (code, params = {}) { - await this.loadMarkets (); - const currency = this.currency (code); - const request = { - 'currency_id': currency['id'], - }; - const response = await this.privatePostBalanceInfo (this.extend (request, params)); - const data = this.safeValue (response, 'response', {}); - const balance = this.safeValue (data, 'entity', {}); - const address = this.safeString (balance, 'address'); - const status = address ? 'ok' : 'none'; - return { - 'currency': code, - 'address': address, - 'tag': undefined, - 'status': status, - 'info': response, - }; - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/' + this.version + '/' + path; - if (api === 'public') { - if (Object.keys (params).length) { - url += '?' + this.urlencode (params); - } - } else { - this.checkRequiredCredentials (); - body = this.urlencode (this.extend ({ - 'nonce': this.nonce (), - }, params)); - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Key': this.apiKey, - 'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } - - async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - const response = await this.fetch2 (path, api, method, params, headers, body); - const errors = this.safeValue (response, 'errors'); - const data = this.safeValue (response, 'response'); - if (errors || !data) { - const authErrorKeys = [ 'Key', 'user_id', 'Sign' ]; - for (let i = 0; i < authErrorKeys.length; i++) { - const errorKey = authErrorKeys[i]; - const errorMessage = this.safeString (errors, errorKey); - if (!errorMessage) { - continue; - } - if (errorKey === 'user_id' && errorMessage.indexOf ('authorization') < 0) { - continue; - } - throw new AuthenticationError (errorMessage); - } - throw new ExchangeError (this.json (errors)); - } - return response; - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/idex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/idex.js index 7d52a5286..c3c14d981 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/idex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/idex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { PAD_WITH_ZERO } = require ('./base/functions/number'); const { InvalidOrder, InsufficientFunds, ExchangeError, ExchangeNotAvailable, DDoSProtection, BadRequest, NotSupported, InvalidAddress, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -241,14 +242,6 @@ module.exports = class idex extends Exchange { return this.parseTickers (response, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // { // market: 'DIL-ETH', @@ -268,16 +261,16 @@ module.exports = class idex extends Exchange { // } const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'baseVolume'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume'); + const baseVolume = this.safeNumber (ticker, 'baseVolume'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume'); const timestamp = this.safeInteger (ticker, 'time'); - const open = this.safeFloat (ticker, 'open'); - const high = this.safeFloat (ticker, 'high'); - const low = this.safeFloat (ticker, 'low'); - const close = this.safeFloat (ticker, 'close'); - const ask = this.safeFloat (ticker, 'ask'); - const bid = this.safeFloat (ticker, 'bid'); - let percentage = this.safeFloat (ticker, 'percentChange'); + const open = this.safeNumber (ticker, 'open'); + const high = this.safeNumber (ticker, 'high'); + const low = this.safeNumber (ticker, 'low'); + const close = this.safeNumber (ticker, 'close'); + const ask = this.safeNumber (ticker, 'ask'); + const bid = this.safeNumber (ticker, 'bid'); + let percentage = this.safeNumber (ticker, 'percentChange'); if (percentage !== undefined) { percentage = 1 + percentage / 100; } @@ -353,11 +346,11 @@ module.exports = class idex extends Exchange { // sequence: 3853 // } const timestamp = this.safeInteger (ohlcv, 'start'); - const open = this.safeFloat (ohlcv, 'open'); - const high = this.safeFloat (ohlcv, 'high'); - const low = this.safeFloat (ohlcv, 'low'); - const close = this.safeFloat (ohlcv, 'close'); - const volume = this.safeFloat (ohlcv, 'volume'); + const open = this.safeNumber (ohlcv, 'open'); + const high = this.safeNumber (ohlcv, 'high'); + const low = this.safeNumber (ohlcv, 'low'); + const close = this.safeNumber (ohlcv, 'close'); + const volume = this.safeNumber (ohlcv, 'volume'); return [ timestamp, open, high, low, close, volume ]; } @@ -419,9 +412,14 @@ module.exports = class idex extends Exchange { // txStatus: 'mined' // } const id = this.safeString (trade, 'fillId'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - const cost = this.safeFloat (trade, 'quoteQuantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'quoteQuantity'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const timestamp = this.safeInteger (trade, 'time'); const marketId = this.safeString (trade, 'market'); const symbol = this.safeSymbol (marketId, market, '-'); @@ -430,7 +428,7 @@ module.exports = class idex extends Exchange { const oppositeSide = (makerSide === 'buy') ? 'sell' : 'buy'; const side = this.safeString (trade, 'side', oppositeSide); const takerOrMaker = this.safeString (trade, 'liquidity', 'taker'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeAsset'); @@ -503,8 +501,8 @@ module.exports = class idex extends Exchange { const result = []; for (let i = 0; i < bookSide.length; i++) { const order = bookSide[i]; - const price = this.safeFloat (order, 0); - const amount = this.safeFloat (order, 1); + const price = this.safeNumber (order, 0); + const amount = this.safeNumber (order, 1); const orderCount = this.safeInteger (order, 2); result.push ([ price, amount, orderCount ]); } @@ -591,16 +589,13 @@ module.exports = class idex extends Exchange { const entry = response[i]; const currencyId = this.safeString (entry, 'asset'); const code = this.safeCurrencyCode (currencyId); - const total = this.safeFloat (entry, 'quantity'); - const free = this.safeFloat (entry, 'availableForTrade'); - const used = this.safeFloat (entry, 'locked'); - result[code] = { - 'free': free, - 'used': used, - 'total': total, - }; + const account = this.account (); + account['total'] = this.safeString (entry, 'quantity'); + account['free'] = this.safeString (entry, 'availableForTrade'); + account['used'] = this.safeString (entry, 'locked'); + result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -821,10 +816,10 @@ module.exports = class idex extends Exchange { const symbol = this.safeSymbol (marketId, market, '-'); const trades = this.parseTrades (fills, market); const type = this.safeString (order, 'type'); - const amount = this.safeFloat (order, 'originalQuantity'); - const filled = this.safeFloat (order, 'executedQuantity'); - const average = this.safeFloat (order, 'avgExecutionPrice'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'originalQuantity'); + const filled = this.safeNumber (order, 'executedQuantity'); + const average = this.safeNumber (order, 'avgExecutionPrice'); + const price = this.safeNumber (order, 'price'); const rawStatus = this.safeString (order, 'status'); const status = this.parseOrderStatus (rawStatus); const fee = { @@ -933,7 +928,7 @@ module.exports = class idex extends Exchange { throw new NotSupported (this.id + ' quoteOrderQuantity is not supported for ' + type + ' orders, only supported for market orders'); } amountEnum = 1; - amount = this.safeFloat (params, 'quoteOrderQuantity'); + amount = this.safeNumber (params, 'quoteOrderQuantity'); } const sideEnum = (side === 'buy') ? 0 : 1; const walletBytes = this.remove0xPrefix (this.walletAddress); @@ -1236,13 +1231,13 @@ module.exports = class idex extends Exchange { } const id = this.safeString2 (transaction, 'depositId', 'withdrawId'); const code = this.safeCurrencyCode (this.safeString (transaction, 'asset'), currency); - const amount = this.safeFloat (transaction, 'quantity'); + const amount = this.safeNumber (transaction, 'quantity'); const txid = this.safeString (transaction, 'txId'); const timestamp = this.safeInteger (transaction, 'txTime'); let fee = undefined; if ('fee' in transaction) { fee = { - 'cost': this.safeFloat (transaction, 'fee'), + 'cost': this.safeNumber (transaction, 'fee'), 'currency': 'ETH', }; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/independentreserve.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/independentreserve.js index 119a216d5..86dcb348b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/independentreserve.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/independentreserve.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -126,11 +127,11 @@ module.exports = class independentreserve extends Exchange { const currencyId = this.safeString (balance, 'CurrencyCode'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'AvailableBalance'); - account['total'] = this.safeFloat (balance, 'TotalBalance'); + account['free'] = this.safeString (balance, 'AvailableBalance'); + account['total'] = this.safeString (balance, 'TotalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -151,16 +152,16 @@ module.exports = class independentreserve extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'LastPrice'); + const last = this.safeNumber (ticker, 'LastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'DayHighestPrice'), - 'low': this.safeFloat (ticker, 'DayLowestPrice'), - 'bid': this.safeFloat (ticker, 'CurrentHighestBidPrice'), + 'high': this.safeNumber (ticker, 'DayHighestPrice'), + 'low': this.safeNumber (ticker, 'DayLowestPrice'), + 'bid': this.safeNumber (ticker, 'CurrentHighestBidPrice'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'CurrentLowestOfferPrice'), + 'ask': this.safeNumber (ticker, 'CurrentLowestOfferPrice'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -169,8 +170,8 @@ module.exports = class independentreserve extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'DayAvgPrice'), - 'baseVolume': this.safeFloat (ticker, 'DayVolumeXbtInSecondaryCurrrency'), + 'average': this.safeNumber (ticker, 'DayAvgPrice'), + 'baseVolume': this.safeNumber (ticker, 'DayVolumeXbtInSecondaryCurrrency'), 'quoteVolume': undefined, 'info': ticker, }; @@ -249,20 +250,10 @@ module.exports = class independentreserve extends Exchange { orderType = 'limit'; } const timestamp = this.parse8601 (this.safeString (order, 'CreatedTimestampUtc')); - const amount = this.safeFloat2 (order, 'VolumeOrdered', 'Volume'); - let filled = this.safeFloat (order, 'VolumeFilled'); - let remaining = this.safeFloat (order, 'Outstanding'); - if (filled === undefined) { - if ((remaining !== undefined) && (amount !== undefined)) { - filled = Math.max (0, amount - remaining); - } - } - if (remaining === undefined) { - if ((filled !== undefined) && (amount !== undefined)) { - remaining = Math.max (0, amount - filled); - } - } - const feeRate = this.safeFloat (order, 'FeePercent'); + const amount = this.safeNumber2 (order, 'VolumeOrdered', 'Volume'); + const filled = this.safeNumber (order, 'VolumeFilled'); + const remaining = this.safeNumber (order, 'Outstanding'); + const feeRate = this.safeNumber (order, 'FeePercent'); let feeCost = undefined; if (feeRate !== undefined) { feeCost = feeRate * filled; @@ -274,10 +265,10 @@ module.exports = class independentreserve extends Exchange { }; const id = this.safeString (order, 'OrderGuid'); const status = this.parseOrderStatus (this.safeString (order, 'Status')); - const cost = this.safeFloat (order, 'Value'); - const average = this.safeFloat (order, 'AvgPrice'); - const price = this.safeFloat (order, 'Price', average); - return { + const cost = this.safeNumber (order, 'Value'); + const average = this.safeNumber (order, 'AvgPrice'); + const price = this.safeNumber (order, 'Price'); + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -299,7 +290,7 @@ module.exports = class independentreserve extends Exchange { 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -387,14 +378,11 @@ module.exports = class independentreserve extends Exchange { const timestamp = this.parse8601 (trade['TradeTimestampUtc']); const id = this.safeString (trade, 'TradeGuid'); const orderId = this.safeString (trade, 'OrderGuid'); - const price = this.safeFloat2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); - const amount = this.safeFloat2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'Price', 'SecondaryCurrencyTradePrice'); + const amountString = this.safeString2 (trade, 'VolumeTraded', 'PrimaryCurrencyAmount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const baseId = this.safeString (trade, 'PrimaryCurrencyCode'); const quoteId = this.safeString (trade, 'SecondaryCurrencyCode'); let marketId = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/indodax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/indodax.js index f1cc33732..05972a887 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/indodax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/indodax.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InsufficientFunds, InvalidOrder, OrderNotFound, AuthenticationError, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,7 +165,7 @@ module.exports = class indodax extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const taker = this.safeFloat (market, 'trade_fee_percent'); + const taker = this.safeNumber (market, 'trade_fee_percent'); const isMaintenance = this.safeInteger (market, 'is_maintenance'); const active = (isMaintenance) ? false : true; const pricePrecision = this.safeInteger (market, 'price_round'); @@ -174,11 +175,11 @@ module.exports = class indodax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'trade_min_traded_currency'), + 'min': this.safeNumber (market, 'trade_min_traded_currency'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'trade_min_base_currency'), + 'min': this.safeNumber (market, 'trade_min_base_currency'), 'max': undefined, }, 'cost': { @@ -216,11 +217,11 @@ module.exports = class indodax extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (used, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (used, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -257,16 +258,16 @@ module.exports = class indodax extends Exchange { const timestamp = this.safeTimestamp (ticker, 'server_time'); const baseVolume = 'vol_' + market['baseId'].toLowerCase (); const quoteVolume = 'vol_' + market['quoteId'].toLowerCase (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -276,8 +277,8 @@ module.exports = class indodax extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, baseVolume), - 'quoteVolume': this.safeFloat (ticker, quoteVolume), + 'baseVolume': this.safeNumber (ticker, baseVolume), + 'quoteVolume': this.safeNumber (ticker, quoteVolume), 'info': ticker, }; } @@ -291,14 +292,11 @@ module.exports = class indodax extends Exchange { } const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, @@ -353,7 +351,7 @@ module.exports = class indodax extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'status', 'open')); let symbol = undefined; let cost = undefined; - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let amount = undefined; let remaining = undefined; let filled = undefined; @@ -367,18 +365,18 @@ module.exports = class indodax extends Exchange { if ((market['baseId'] === 'idr') && ('remain_rp' in order)) { baseId = 'rp'; } - cost = this.safeFloat (order, 'order_' + quoteId); + cost = this.safeNumber (order, 'order_' + quoteId); if (cost) { amount = cost / price; - const remainingCost = this.safeFloat (order, 'remain_' + quoteId); + const remainingCost = this.safeNumber (order, 'remain_' + quoteId); if (remainingCost !== undefined) { remaining = remainingCost / price; filled = amount - remaining; } } else { - amount = this.safeFloat (order, 'order_' + baseId); + amount = this.safeNumber (order, 'order_' + baseId); cost = price * amount; - remaining = this.safeFloat (order, 'remain_' + baseId); + remaining = this.safeNumber (order, 'remain_' + baseId); filled = amount - remaining; } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/itbit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/itbit.js index 552bb0de5..a46080ccc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/itbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/itbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -114,25 +115,25 @@ module.exports = class itbit extends Exchange { throw new ExchangeError (this.id + ' fetchTicker returned a bad response: ' + this.json (ticker)); } const timestamp = this.parse8601 (serverTimeUTC); - const vwap = this.safeFloat (ticker, 'vwap24h'); - const baseVolume = this.safeFloat (ticker, 'volume24h'); + const vwap = this.safeNumber (ticker, 'vwap24h'); + const baseVolume = this.safeNumber (ticker, 'volume24h'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'lastPrice'); + const last = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'openToday'), + 'open': this.safeNumber (ticker, 'openToday'), 'close': last, 'last': last, 'previousClose': undefined, @@ -179,23 +180,20 @@ module.exports = class itbit extends Exchange { const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); const side = this.safeString (trade, 'direction'); const orderId = this.safeString (trade, 'orderId'); - let feeCost = this.safeFloat (trade, 'commissionPaid'); + let feeCost = this.safeNumber (trade, 'commissionPaid'); const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - let rebatesApplied = this.safeFloat (trade, 'rebatesApplied'); + let rebatesApplied = this.safeNumber (trade, 'rebatesApplied'); if (rebatesApplied !== undefined) { rebatesApplied = -rebatesApplied; } const rebateCurrencyId = this.safeString (trade, 'rebateCurrency'); const rebateCurrency = this.safeCurrencyCode (rebateCurrencyId); - const price = this.safeFloat2 (trade, 'price', 'rate'); - const amount = this.safeFloat2 (trade, 'currency1Amount', 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'price', 'rate'); + const amountString = this.safeString2 (trade, 'currency1Amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; const marketId = this.safeString (trade, 'instrument'); if (marketId !== undefined) { @@ -317,7 +315,7 @@ module.exports = class itbit extends Exchange { 'txid': txnHash, 'type': transactionType, 'status': status, - 'amount': this.safeFloat (item, 'amount'), + 'amount': this.safeNumber (item, 'amount'), 'fee': undefined, 'info': item, }); @@ -417,11 +415,11 @@ module.exports = class itbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'availableBalance'); - account['total'] = this.safeFloat (balance, 'totalBalance'); + account['free'] = this.safeString (balance, 'availableBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchWallets (params = {}) { @@ -512,26 +510,16 @@ module.exports = class itbit extends Exchange { const type = this.safeString (order, 'type'); const symbol = this.markets_by_id[order['instrument']]['symbol']; const timestamp = this.parse8601 (order['createdTime']); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'amountFilled'); - let remaining = undefined; - let cost = undefined; + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'amountFilled'); const fee = undefined; - const price = this.safeFloat (order, 'price'); - const average = this.safeFloat (order, 'volumeWeightedAveragePrice'); - if (filled !== undefined) { - if (amount !== undefined) { - remaining = amount - filled; - } - if (average !== undefined) { - cost = filled * average; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'volumeWeightedAveragePrice'); const clientOrderId = this.safeString (order, 'clientOrderIdentifier'); const id = this.safeString (order, 'id'); const postOnlyString = this.safeString (order, 'postOnly'); const postOnly = (postOnlyString === 'True'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -546,15 +534,15 @@ module.exports = class itbit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, // 'trades': this.parseTrades (order['trades'], market), 'trades': undefined, - }; + }); } nonce () { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kraken.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kraken.js index 198ee4cf8..514ed0094 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kraken.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kraken.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { BadSymbol, ExchangeNotAvailable, ArgumentsRequired, PermissionDenied, AuthenticationError, ExchangeError, OrderNotFound, DDoSProtection, InvalidNonce, InsufficientFunds, CancelPending, InvalidOrder, InvalidAddress, RateLimitExceeded } = require ('./base/errors'); const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -297,26 +298,38 @@ module.exports = class kraken extends Exchange { // } // } // - const keys = Object.keys (response['result']); + const markets = this.safeValue (response, 'result', {}); + const keys = Object.keys (markets); let result = []; for (let i = 0; i < keys.length; i++) { const id = keys[i]; - const market = response['result'][id]; - const baseId = market['base']; - const quoteId = market['quote']; + const market = markets[id]; + const baseId = this.safeString (market, 'base'); + const quoteId = this.safeString (market, 'quote'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const darkpool = id.indexOf ('.d') >= 0; - const symbol = darkpool ? market['altname'] : (base + '/' + quote); + const altname = this.safeString (market, 'altname'); + const symbol = darkpool ? altname : (base + '/' + quote); + const makerFees = this.safeValue (market, 'fees_maker', []); + const firstMakerFee = this.safeValue (makerFees, 0, []); + const firstMakerFeeRate = this.safeNumber (firstMakerFee, 1); let maker = undefined; - if ('fees_maker' in market) { - maker = parseFloat (market['fees_maker'][0][1]) / 100; + if (firstMakerFeeRate !== undefined) { + maker = parseFloat (firstMakerFeeRate) / 100; + } + const takerFees = this.safeValue (market, 'fees', []); + const firstTakerFee = this.safeValue (takerFees, 0, []); + const firstTakerFeeRate = this.safeNumber (firstTakerFee, 1); + let taker = undefined; + if (firstTakerFeeRate !== undefined) { + taker = parseFloat (firstTakerFeeRate) / 100; } const precision = { - 'amount': market['lot_decimals'], - 'price': market['pair_decimals'], + 'amount': this.safeInteger (market, 'lot_decimals'), + 'price': this.safeInteger (market, 'pair_decimals'), }; - const minAmount = this.safeFloat (market, 'ordermin'); + const minAmount = this.safeNumber (market, 'ordermin'); result.push ({ 'id': id, 'symbol': symbol, @@ -328,7 +341,7 @@ module.exports = class kraken extends Exchange { 'info': market, 'altname': market['altname'], 'maker': maker, - 'taker': parseFloat (market['fees'][0][1]) / 100, + 'taker': taker, 'active': true, 'precision': precision, 'limits': { @@ -451,7 +464,7 @@ module.exports = class kraken extends Exchange { await this.loadMarkets (); this.checkRequiredCredentials (); const response = await this.privatePostTradeVolume (params); - const tradedVolume = this.safeFloat (response['result'], 'volume'); + const tradedVolume = this.safeNumber (response['result'], 'volume'); const tiers = this.fees['trading']['tiers']; let taker = tiers['taker'][1]; let maker = tiers['maker'][1]; @@ -473,8 +486,8 @@ module.exports = class kraken extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - const amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + const amount = this.safeNumber (bidask, amountKey); const timestamp = this.safeInteger (bidask, 2); return [ price, amount, timestamp ]; } @@ -512,7 +525,14 @@ module.exports = class kraken extends Exchange { // } // const result = this.safeValue (response, 'result', {}); - const orderbook = this.safeValue (result, market['id']); + let orderbook = this.safeValue (result, market['id']); + // sometimes kraken returns wsname instead of market id + // https://github.com/ccxt/ccxt/issues/8662 + const marketInfo = this.safeValue (market, 'info', {}); + const wsName = this.safeValue (marketInfo, 'wsname'); + if (wsName !== undefined) { + orderbook = this.safeValue (result, wsName, orderbook); + } return this.parseOrderBook (orderbook); } @@ -540,7 +560,7 @@ module.exports = class kraken extends Exchange { 'ask': parseFloat (ticker['a'][0]), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'o'), + 'open': this.safeNumber (ticker, 'o'), 'close': last, 'last': last, 'previousClose': undefined, @@ -611,11 +631,11 @@ module.exports = class kraken extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 6), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 6), ]; } @@ -682,24 +702,24 @@ module.exports = class kraken extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'asset'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); } else { direction = 'in'; } - const time = this.safeFloat (item, 'time'); + const time = this.safeNumber (item, 'time'); let timestamp = undefined; if (time !== undefined) { timestamp = parseInt (time * 1000); } const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, @@ -823,9 +843,8 @@ module.exports = class kraken extends Exchange { let timestamp = undefined; let side = undefined; let type = undefined; - let price = undefined; - let amount = undefined; - let cost = undefined; + let priceString = undefined; + let amountString = undefined; let id = undefined; let orderId = undefined; let fee = undefined; @@ -834,8 +853,8 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 2); side = (trade[3] === 's') ? 'sell' : 'buy'; type = (trade[4] === 'l') ? 'limit' : 'market'; - price = this.safeFloat (trade, 0); - amount = this.safeFloat (trade, 1); + priceString = this.safeString (trade, 0); + amountString = this.safeString (trade, 1); const tradeLength = trade.length; if (tradeLength > 6) { id = this.safeString (trade, 6); // artificially added as per #1794 @@ -856,15 +875,15 @@ module.exports = class kraken extends Exchange { timestamp = this.safeTimestamp (trade, 'time'); side = this.safeString (trade, 'type'); type = this.safeString (trade, 'ordertype'); - price = this.safeFloat (trade, 'price'); - amount = this.safeFloat (trade, 'vol'); + priceString = this.safeString (trade, 'price'); + amountString = this.safeString (trade, 'vol'); if ('fee' in trade) { let currency = undefined; if (market !== undefined) { currency = market['quote']; } fee = { - 'cost': this.safeFloat (trade, 'fee'), + 'cost': this.safeNumber (trade, 'fee'), 'currency': currency, }; } @@ -872,11 +891,9 @@ module.exports = class kraken extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'order': orderId, @@ -951,10 +968,10 @@ module.exports = class kraken extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -983,15 +1000,15 @@ module.exports = class kraken extends Exchange { if (type === 'limit') { request['price'] = this.priceToPrecision (symbol, price); } else if ((type === 'stop-loss') || (type === 'take-profit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice', price); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice', price); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument or a price/stopPrice parameter for a ' + type + ' order'); } else { request['price'] = this.priceToPrecision (symbol, stopPrice); } } else if ((type === 'stop-loss-limit') || (type === 'take-profit-limit')) { - const stopPrice = this.safeFloat2 (params, 'price', 'stopPrice'); - const limitPrice = this.safeFloat (params, 'price2'); + const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice'); + const limitPrice = this.safeNumber (params, 'price2'); const stopPriceDefined = (stopPrice !== undefined); const limitPriceDefined = (limitPrice !== undefined); if (stopPriceDefined && limitPriceDefined) { @@ -1100,10 +1117,10 @@ module.exports = class kraken extends Exchange { if (orderDescription !== undefined) { const parts = orderDescription.split (' '); side = this.safeString (parts, 0); - amount = this.safeFloat (parts, 1); + amount = this.safeNumber (parts, 1); marketId = this.safeString (parts, 2); type = this.safeString (parts, 4); - price = this.safeFloat (parts, 5); + price = this.safeNumber (parts, 5); } side = this.safeString (description, 'type', side); type = this.safeString (description, 'ordertype', type); @@ -1117,27 +1134,23 @@ module.exports = class kraken extends Exchange { market = this.getDelistedMarketById (marketId); } const timestamp = this.safeTimestamp (order, 'opentm'); - amount = this.safeFloat (order, 'vol', amount); - const filled = this.safeFloat (order, 'vol_exec'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = amount - filled; - } + amount = this.safeNumber (order, 'vol', amount); + const filled = this.safeNumber (order, 'vol_exec'); let fee = undefined; - const cost = this.safeFloat (order, 'cost'); - price = this.safeFloat (description, 'price', price); + const cost = this.safeNumber (order, 'cost'); + price = this.safeNumber (description, 'price', price); if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (description, 'price2'); + price = this.safeNumber (description, 'price2'); } if ((price === undefined) || (price === 0.0)) { - price = this.safeFloat (order, 'price', price); + price = this.safeNumber (order, 'price', price); } - const average = this.safeFloat (order, 'price'); + const average = this.safeNumber (order, 'price'); if (market !== undefined) { symbol = market['symbol']; if ('fee' in order) { const flags = order['oflags']; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); fee = { 'cost': feeCost, 'rate': undefined, @@ -1161,8 +1174,8 @@ module.exports = class kraken extends Exchange { if (rawTrades !== undefined) { trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id }); } - const stopPrice = this.safeFloat (order, 'stopprice'); - return { + const stopPrice = this.safeNumber (order, 'stopprice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -1181,10 +1194,10 @@ module.exports = class kraken extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -1534,10 +1547,10 @@ module.exports = class kraken extends Exchange { const currencyId = this.safeString (transaction, 'asset'); const code = this.safeCurrencyCode (currencyId, currency); const address = this.safeString (transaction, 'info'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.safeString (transaction, 'type'); // injected from the outside - let feeCost = this.safeFloat (transaction, 'fee'); + let feeCost = this.safeNumber (transaction, 'fee'); if (feeCost === undefined) { if (type === 'deposit') { feeCost = 0; @@ -1714,7 +1727,7 @@ module.exports = class kraken extends Exchange { throw new ExchangeError (this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)"); } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const request = { // 'txid': 'comma delimited list of transaction ids to restrict output to', diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kucoin.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kucoin.js index bcb058989..0b5aca5af 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kucoin.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kucoin.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -45,6 +46,7 @@ module.exports = class kucoin extends Exchange { 'fetchTrades': true, 'fetchWithdrawals': true, 'withdraw': true, + 'transfer': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg', @@ -52,6 +54,7 @@ module.exports = class kucoin extends Exchange { 'api': { 'public': 'https://openapi-v2.kucoin.com', 'private': 'https://openapi-v2.kucoin.com', + 'futuresPrivate': 'https://api-futures.kucoin.com', }, 'test': { 'public': 'https://openapi-sandbox.kucoin.com', @@ -160,6 +163,15 @@ module.exports = class kucoin extends Exchange { 'stop-order/cancel', ], }, + 'futuresPrivate': { + 'get': [ + 'account-overview', + 'positions', + ], + 'post': [ + 'transfer-out', + ], + }, }, 'timeframes': { '1m': '1min', @@ -184,6 +196,7 @@ module.exports = class kucoin extends Exchange { 'order_not_exist_or_not_allow_to_cancel': InvalidOrder, // {"code":"400100","msg":"order_not_exist_or_not_allow_to_cancel"} 'Order size below the minimum requirement.': InvalidOrder, // {"code":"400100","msg":"Order size below the minimum requirement."} 'The withdrawal amount is below the minimum requirement.': ExchangeError, // {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."} + 'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, // {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"} '400': BadRequest, '401': AuthenticationError, '403': NotSupported, @@ -240,9 +253,7 @@ module.exports = class kucoin extends Exchange { 'version': 'v1', 'symbolSeparator': '-', 'fetchMyTradesMethod': 'private_get_fills', - 'fetchBalance': { - 'type': 'trade', // or 'main' - }, + 'fetchBalance': 'trade', // endpoint versions 'versions': { 'public': { @@ -262,6 +273,25 @@ module.exports = class kucoin extends Exchange { 'accounts/sub-transfer': 'v2', }, }, + 'futuresPrivate': { + 'GET': { + 'account-overview': 'v1', + 'positions': 'v1', + }, + 'POST': { + 'transfer-out': 'v2', + }, + }, + }, + 'accountsByType': { + 'trade': 'trade', + 'trading': 'trade', + 'margin': 'margin', + 'main': 'main', + 'futures': 'contract', + 'contract': 'contract', + 'pool': 'pool', + 'pool-x': 'pool', }, }, }); @@ -342,11 +372,11 @@ module.exports = class kucoin extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const active = this.safeValue (market, 'enableTrading'); - const baseMaxSize = this.safeFloat (market, 'baseMaxSize'); - const baseMinSize = this.safeFloat (market, 'baseMinSize'); - const quoteMaxSize = this.safeFloat (market, 'quoteMaxSize'); - const quoteMinSize = this.safeFloat (market, 'quoteMinSize'); - // const quoteIncrement = this.safeFloat (market, 'quoteIncrement'); + const baseMaxSize = this.safeNumber (market, 'baseMaxSize'); + const baseMinSize = this.safeNumber (market, 'baseMinSize'); + const quoteMaxSize = this.safeNumber (market, 'quoteMaxSize'); + const quoteMinSize = this.safeNumber (market, 'quoteMinSize'); + // const quoteIncrement = this.safeNumber (market, 'quoteIncrement'); const precision = { 'amount': this.precisionFromString (this.safeString (market, 'baseIncrement')), 'price': this.precisionFromString (this.safeString (market, 'priceIncrement')), @@ -357,7 +387,7 @@ module.exports = class kucoin extends Exchange { 'max': baseMaxSize, }, 'price': { - 'min': this.safeFloat (market, 'priceIncrement'), + 'min': this.safeNumber (market, 'priceIncrement'), 'max': quoteMaxSize / baseMinSize, }, 'cost': { @@ -408,7 +438,7 @@ module.exports = class kucoin extends Exchange { const precision = this.safeInteger (entry, 'precision'); const isWithdrawEnabled = this.safeValue (entry, 'isWithdrawEnabled', false); const isDepositEnabled = this.safeValue (entry, 'isDepositEnabled', false); - const fee = this.safeFloat (entry, 'withdrawalMinFee'); + const fee = this.safeNumber (entry, 'withdrawalMinFee'); const active = (isWithdrawEnabled && isDepositEnabled); result[code] = { 'id': id, @@ -475,7 +505,7 @@ module.exports = class kucoin extends Exchange { const response = await this.privateGetWithdrawalsQuotas (this.extend (request, params)); const data = response['data']; const withdrawFees = {}; - withdrawFees[code] = this.safeFloat (data, 'withdrawMinFee'); + withdrawFees[code] = this.safeNumber (data, 'withdrawMinFee'); return { 'info': response, 'withdraw': withdrawFees, @@ -522,35 +552,35 @@ module.exports = class kucoin extends Exchange { // "mark": 0 // } // - let percentage = this.safeFloat (ticker, 'changeRate'); + let percentage = this.safeNumber (ticker, 'changeRate'); if (percentage !== undefined) { percentage = percentage * 100; } - const last = this.safeFloat2 (ticker, 'last', 'lastTradedPrice'); + const last = this.safeNumber2 (ticker, 'last', 'lastTradedPrice'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '-'); - const baseVolume = this.safeFloat (ticker, 'vol'); - const quoteVolume = this.safeFloat (ticker, 'volValue'); + const baseVolume = this.safeNumber (ticker, 'vol'); + const quoteVolume = this.safeNumber (ticker, 'volValue'); const vwap = this.vwap (baseVolume, quoteVolume); const timestamp = this.safeInteger2 (ticker, 'time', 'datetime'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, - 'change': this.safeFloat (ticker, 'changePrice'), + 'change': this.safeNumber (ticker, 'changePrice'), 'percentage': percentage, - 'average': this.safeFloat (ticker, 'averagePrice'), + 'average': this.safeNumber (ticker, 'averagePrice'), 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, @@ -634,11 +664,11 @@ module.exports = class kucoin extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 5), ]; } @@ -836,16 +866,18 @@ module.exports = class kucoin extends Exchange { // 'marginMode': 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned // 'autoBorrow': false, // The system will first borrow you funds at the optimal interest rate and then place an order for you }; - if (type !== 'market') { - request['price'] = this.priceToPrecision (symbol, price); - request['size'] = this.amountToPrecision (symbol, amount); - } else { - if (this.safeValue (params, 'quoteAmount')) { - // used to create market order by quote amount - https://github.com/ccxt/ccxt/issues/4876 - request['funds'] = this.amountToPrecision (symbol, amount); + const quoteAmount = this.safeNumber2 (params, 'cost', 'funds'); + if (type === 'market') { + if (quoteAmount !== undefined) { + params = this.omit (params, [ 'cost', 'funds' ]); + // kucoin uses base precision even for quote values + request['funds'] = this.amountToPrecision (symbol, quoteAmount); } else { request['size'] = this.amountToPrecision (symbol, amount); } + } else { + request['price'] = this.priceToPrecision (symbol, price); + request['size'] = this.amountToPrecision (symbol, amount); } const response = await this.privatePostOrders (this.extend (request, params)); // @@ -879,8 +911,10 @@ module.exports = class kucoin extends Exchange { 'fee': undefined, 'trades': undefined, }; - if (!this.safeValue (params, 'quoteAmount')) { + if (quoteAmount === undefined) { order['amount'] = amount; + } else { + order['cost'] = quoteAmount; } return order; } @@ -1056,15 +1090,18 @@ module.exports = class kucoin extends Exchange { const type = this.safeString (order, 'type'); const timestamp = this.safeInteger (order, 'createdAt'); const datetime = this.iso8601 (timestamp); - let price = this.safeFloat (order, 'price'); + let price = this.safeNumber (order, 'price'); + if (price === 0.0) { + // market orders + price = undefined; + } const side = this.safeString (order, 'side'); const feeCurrencyId = this.safeString (order, 'feeCurrency'); const feeCurrency = this.safeCurrencyCode (feeCurrencyId); - const feeCost = this.safeFloat (order, 'fee'); - const amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat (order, 'dealSize'); - const cost = this.safeFloat (order, 'dealFunds'); - const remaining = amount - filled; + const feeCost = this.safeNumber (order, 'fee'); + const amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber (order, 'dealSize'); + const cost = this.safeNumber (order, 'dealFunds'); // bool const isActive = this.safeValue (order, 'isActive', false); const cancelExist = this.safeValue (order, 'cancelExist', false); @@ -1074,20 +1111,11 @@ module.exports = class kucoin extends Exchange { 'currency': feeCurrency, 'cost': feeCost, }; - if (type === 'market') { - if (price === 0.0) { - if ((cost !== undefined) && (filled !== undefined)) { - if ((cost > 0) && (filled > 0)) { - price = cost / filled; - } - } - } - } const clientOrderId = this.safeString (order, 'clientOid'); const timeInForce = this.safeString (order, 'timeInForce'); - const stopPrice = this.safeFloat (order, 'stopPrice'); + const stopPrice = this.safeNumber (order, 'stopPrice'); const postOnly = this.safeValue (order, 'postOnly'); - return { + return this.safeOrder ({ 'id': orderId, 'clientOrderId': clientOrderId, 'symbol': symbol, @@ -1100,7 +1128,7 @@ module.exports = class kucoin extends Exchange { 'stopPrice': stopPrice, 'cost': cost, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'timestamp': timestamp, 'datetime': datetime, 'fee': fee, @@ -1109,7 +1137,7 @@ module.exports = class kucoin extends Exchange { 'lastTradeTimestamp': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -1310,7 +1338,6 @@ module.exports = class kucoin extends Exchange { const id = this.safeString2 (trade, 'tradeId', 'id'); const orderId = this.safeString (trade, 'orderId'); const takerOrMaker = this.safeString (trade, 'liquidity'); - const amount = this.safeFloat2 (trade, 'size', 'amount'); let timestamp = this.safeInteger (trade, 'time'); if (timestamp !== undefined) { timestamp = parseInt (timestamp / 1000000); @@ -1321,10 +1348,13 @@ module.exports = class kucoin extends Exchange { timestamp = timestamp * 1000; } } - const price = this.safeFloat2 (trade, 'price', 'dealPrice'); + const priceString = this.safeString2 (trade, 'price', 'dealPrice'); + const amountString = this.safeString2 (trade, 'size', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const side = this.safeString (trade, 'side'); let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'feeCurrency'); let feeCurrency = this.safeCurrencyCode (feeCurrencyId); @@ -1336,20 +1366,16 @@ module.exports = class kucoin extends Exchange { fee = { 'cost': feeCost, 'currency': feeCurrency, - 'rate': this.safeFloat (trade, 'feeRate'), + 'rate': this.safeNumber (trade, 'feeRate'), }; } let type = this.safeString (trade, 'type'); if (type === 'match') { type = undefined; } - let cost = this.safeFloat2 (trade, 'funds', 'dealValue'); + let cost = this.safeNumber2 (trade, 'funds', 'dealValue'); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } return { 'info': trade, @@ -1445,7 +1471,7 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); let address = this.safeString (transaction, 'address'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let txid = this.safeString (transaction, 'walletTxId'); if (txid !== undefined) { const txidParts = txid.split ('@'); @@ -1463,7 +1489,7 @@ module.exports = class kucoin extends Exchange { const rawStatus = this.safeString (transaction, 'status'); const status = this.parseTransactionStatus (rawStatus); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { let rate = undefined; if (amount !== undefined) { @@ -1644,45 +1670,180 @@ module.exports = class kucoin extends Exchange { async fetchBalance (params = {}) { await this.loadMarkets (); - let type = undefined; - const request = {}; - if ('type' in params) { - type = params['type']; - if (type !== undefined) { - request['type'] = type; - } - params = this.omit (params, 'type'); + const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'trade'); + const requestedType = this.safeString (params, 'type', defaultType); + const accountsByType = this.safeValue (this.options, 'accountsByType'); + const type = this.safeString (accountsByType, requestedType); + if (type === undefined) { + const keys = Object.keys (accountsByType); + throw new ExchangeError (this.id + ' type must be one of ' + keys.join (', ')); + } + params = this.omit (params, 'type'); + if (type === 'contract') { + // futures api requires a futures apiKey + // only fetches one balance at a time + // by default it will only fetch the BTC balance of the futures account + // you can send 'currency' in params to fetch other currencies + // fetchBalance ({ 'type': 'futures', 'currency': 'USDT' }) + const response = await this.futuresPrivateGetAccountOverview (params); + // + // { + // code: '200000', + // data: { + // accountEquity: 0.00005, + // unrealisedPNL: 0, + // marginBalance: 0.00005, + // positionMargin: 0, + // orderMargin: 0, + // frozenFunds: 0, + // availableBalance: 0.00005, + // currency: 'XBT' + // } + // } + // + const data = this.safeValue (response, 'data'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (data, 'availableBalance'); + account['total'] = this.safeString (data, 'accountEquity'); + const result = { 'info': response }; + result[code] = account; + return this.parseBalance (result, false); } else { - const options = this.safeValue (this.options, 'fetchBalance', {}); - type = this.safeString (options, 'type', 'trade'); - } - const response = await this.privateGetAccounts (this.extend (request, params)); - // - // { - // "code":"200000", - // "data":[ - // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, - // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, - // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, - // ] - // } - // - const data = this.safeValue (response, 'data', []); - const result = { 'info': response }; - for (let i = 0; i < data.length; i++) { - const balance = data[i]; - const balanceType = this.safeString (balance, 'type'); - if (balanceType === type) { - const currencyId = this.safeString (balance, 'currency'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'holds'); - result[code] = account; + const request = { + 'type': type, + }; + const response = await this.privateGetAccounts (this.extend (request, params)); + // + // { + // "code":"200000", + // "data":[ + // {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"}, + // {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"}, + // {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"}, + // ] + // } + // + const data = this.safeValue (response, 'data', []); + const result = { 'info': response }; + for (let i = 0; i < data.length; i++) { + const balance = data[i]; + const balanceType = this.safeString (balance, 'type'); + if (balanceType === type) { + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['total'] = this.safeString (balance, 'balance'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'holds'); + result[code] = account; + } } + return this.parseBalance (result, false); + } + } + + async transfer (code, amount, fromAccount, toAccount, params = {}) { + await this.loadMarkets (); + const currency = this.currency (code); + const requestedAmount = this.currencyToPrecision (code, amount); + const accountsById = this.safeValue (this.options, 'accountsByType', {}); + const fromId = this.safeString (accountsById, fromAccount); + if (fromId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' fromAccount must be one of ' + keys.join (', ')); + } + const toId = this.safeString (accountsById, toAccount); + if (toId === undefined) { + const keys = Object.keys (accountsById); + throw new ExchangeError (this.id + ' toAccount must be one of ' + keys.join (', ')); + } + if (fromId === 'contract') { + if (toId !== 'main') { + throw new ExchangeError (this.id + ' only supports transferring from futures account to main account'); + } + const request = { + 'currency': currency['id'], + 'amount': requestedAmount, + }; + if (!('bizNo' in params)) { + // it doesn't like more than 24 characters + request['bizNo'] = this.uuid22 (); + } + const response = await this.futuresPrivatePostTransferOut (this.extend (request, params)); + // + // { + // code: '200000', + // data: { + // applyId: '605a87217dff1500063d485d', + // bizNo: 'bcd6e5e1291f4905af84dc', + // payAccountType: 'CONTRACT', + // payTag: 'DEFAULT', + // remark: '', + // recAccountType: 'MAIN', + // recTag: 'DEFAULT', + // recRemark: '', + // recSystem: 'KUCOIN', + // status: 'PROCESSING', + // currency: 'XBT', + // amount: '0.00001', + // fee: '0', + // sn: '573688685663948', + // reason: '', + // createdAt: 1616545569000, + // updatedAt: 1616545569000 + // } + // } + // + const data = this.safeValue (response, 'data'); + const timestamp = this.safeInteger (data, 'createdAt'); + const id = this.safeString (data, 'applyId'); + const currencyId = this.safeString (data, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const amount = this.safeNumber (data, 'amount'); + const rawStatus = this.safeString (data, 'status'); + let status = undefined; + if (rawStatus === 'PROCESSING') { + status = 'pending'; + } + return { + 'info': response, + 'currency': code, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'amount': amount, + 'fromAccount': fromId, + 'toAccount': toId, + 'id': id, + 'status': status, + }; + } else { + const request = { + 'currency': currency['id'], + 'from': fromId, + 'to': toId, + 'amount': requestedAmount, + }; + if (!('clientOid' in params)) { + request['clientOid'] = this.uuid (); + } + const response = await this.privatePostAccountsInnerTransfer (this.extend (request, params)); + // { code: '200000', data: { orderId: '605a6211e657f00006ad0ad6' } } + const data = this.safeValue (response, 'data'); + const id = this.safeString (data, 'orderId'); + return { + 'info': response, + 'id': id, + 'timestamp': undefined, + 'datetime': undefined, + 'currency': code, + 'amount': requestedAmount, + 'fromAccount': fromId, + 'toAccount': toId, + 'status': undefined, + }; } - return this.parseBalance (result); } async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) { @@ -1770,11 +1931,11 @@ module.exports = class kucoin extends Exchange { const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'code': code, }; - const amount = this.safeFloat (item, 'amount'); - const after = this.safeFloat (item, 'balance'); + const amount = this.safeNumber (item, 'amount'); + const after = this.safeNumber (item, 'balance'); const direction = this.safeString (item, 'direction'); let before = undefined; if (after !== undefined && amount !== undefined) { @@ -1824,6 +1985,94 @@ module.exports = class kucoin extends Exchange { return this.safeString (types, type, type); } + async fetchPositions (symbols = undefined, params = {}) { + const response = await this.futuresPrivateGetPositions (params); + // + // { + // code: '200000', + // data: [ + // { + // id: '605a9772a229ab0006408258', + // symbol: 'XBTUSDTM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746099, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54371.92, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'USDT', + // isInverse: false + // }, + // { + // id: '605a9772026ac900066550df', + // symbol: 'XBTUSDM', + // autoDeposit: false, + // maintMarginReq: 0.005, + // riskLimit: 200, + // realLeverage: 0, + // crossMode: false, + // delevPercentage: 0, + // currentTimestamp: 1616549746110, + // currentQty: 0, + // currentCost: 0, + // currentComm: 0, + // unrealisedCost: 0, + // realisedGrossCost: 0, + // realisedCost: 0, + // isOpen: false, + // markPrice: 54354.76, + // markValue: 0, + // posCost: 0, + // posCross: 0, + // posInit: 0, + // posComm: 0, + // posLoss: 0, + // posMargin: 0, + // posMaint: 0, + // maintMargin: 0, + // realisedGrossPnl: 0, + // realisedPnl: 0, + // unrealisedPnl: 0, + // unrealisedPnlPcnt: 0, + // unrealisedRoePcnt: 0, + // avgEntryPrice: 0, + // liquidationPrice: 0, + // bankruptPrice: 0, + // settleCurrency: 'XBT', + // isInverse: true + // } + // ] + // } + // + return this.safeValue (response, 'data', response); + } + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { // // the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint @@ -1840,16 +2089,16 @@ module.exports = class kucoin extends Exchange { let endpart = ''; headers = (headers !== undefined) ? headers : {}; if (Object.keys (query).length) { - if (method !== 'GET') { + if ((method === 'GET') || (method === 'DELETE')) { + endpoint += '?' + this.urlencode (query); + } else { body = this.json (query); endpart = body; headers['Content-Type'] = 'application/json'; - } else { - endpoint += '?' + this.urlencode (query); } } const url = this.urls['api'][api] + endpoint; - if (api === 'private') { + if ((api === 'private') || (api === 'futuresPrivate')) { this.checkRequiredCredentials (); const timestamp = this.nonce ().toString (); headers = this.extend ({ @@ -1892,8 +2141,8 @@ module.exports = class kucoin extends Exchange { // { code: '200000', data: { ... }} // const errorCode = this.safeString (response, 'code'); - const message = this.safeString (response, 'msg'); - this.throwExactlyMatchedException (this.exceptions['exact'], message, message); - this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, message); + const message = this.safeString (response, 'msg', ''); + this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message); + this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, this.id + ' ' + message); } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kuna.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kuna.js index e652171d1..0067e406f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kuna.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/kuna.js @@ -2,12 +2,13 @@ // --------------------------------------------------------------------------- -const acx = require ('./acx.js'); -const { ArgumentsRequired } = require ('./base/errors'); +const Exchange = require ('./base/Exchange'); +const { ArgumentsRequired, InsufficientFunds, OrderNotFound } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- -module.exports = class kuna extends acx { +module.exports = class kuna extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'kuna', @@ -17,14 +18,24 @@ module.exports = class kuna extends acx { 'version': 'v2', 'has': { 'CORS': false, - 'fetchTickers': true, + 'cancelOrder': true, + 'createOrder': true, + 'fetchBalance': true, + 'fetchMarkets': true, + 'fetchMyTrades': true, 'fetchOHLCV': 'emulated', 'fetchOpenOrders': true, - 'fetchMyTrades': true, + 'fetchOrder': true, + 'fetchOrderBook': true, + 'fetchTicker': true, + 'fetchTickers': true, + 'fetchTime': true, + 'fetchTrades': true, 'withdraw': false, }, 'timeframes': undefined, 'urls': { + 'extension': '.json', 'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4', 'logo': 'https://user-images.githubusercontent.com/51840849/87153927-f0578b80-c2c0-11ea-84b6-74612568e9e1.jpg', 'api': 'https://kuna.io', @@ -32,8 +43,47 @@ module.exports = class kuna extends acx { 'doc': 'https://kuna.io/documents/api', 'fees': 'https://kuna.io/documents/api', }, + 'api': { + 'public': { + 'get': [ + 'depth', // Get depth or specified market Both asks and bids are sorted from highest price to lowest. + 'k_with_pending_trades', // Get K data with pending trades, which are the trades not included in K data yet, because there's delay between trade generated and processed by K data generator + 'k', // Get OHLC(k line) of specific market + 'markets', // Get all available markets + 'order_book', // Get the order book of specified market + 'order_book/{market}', + 'tickers', // Get ticker of all markets + 'tickers/{market}', // Get ticker of specific market + 'timestamp', // Get server current time, in seconds since Unix epoch + 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order. + 'trades/{market}', + ], + }, + 'private': { + 'get': [ + 'members/me', // Get your profile and accounts info + 'deposits', // Get your deposits history + 'deposit', // Get details of specific deposit + 'deposit_address', // Where to deposit The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case. + 'orders', // Get your orders, results is paginated + 'order', // Get information of specified order + 'trades/my', // Get your executed trades Trades are sorted in reverse creation order. + 'withdraws', // Get your cryptocurrency withdraws + 'withdraw', // Get your cryptocurrency withdraw + ], + 'post': [ + 'orders', // Create a Sell/Buy order + 'orders/multi', // Create multiple sell/buy orders + 'orders/clear', // Cancel all my orders + 'order/delete', // Cancel an order + 'withdraw', // Create a withdraw + ], + }, + }, 'fees': { 'trading': { + 'tierBased': false, + 'percentage': true, 'taker': 0.25 / 100, 'maker': 0.25 / 100, }, @@ -56,9 +106,24 @@ module.exports = class kuna extends acx { }, }, }, + 'commonCurrencies': { + 'PLA': 'Plair', + }, + 'exceptions': { + '2002': InsufficientFunds, + '2003': OrderNotFound, + }, }); } + async fetchTime (params = {}) { + const response = await this.publicGetTimestamp (params); + // + // 1594911427 + // + return response * 1000; + } + async fetchMarkets (params = {}) { const quotes = [ 'btc', 'eth', 'eurs', 'rub', 'uah', 'usd', 'usdt', 'gol' ]; const pricePrecisions = { @@ -114,24 +179,100 @@ module.exports = class kuna extends acx { return markets; } - async fetchL3OrderBook (symbol, limit = undefined, params = {}) { - return await this.fetchOrderBook (symbol, limit, params); - } - - async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); - } + async fetchOrderBook (symbol, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; - const response = await this.privateGetOrders (this.extend (request, params)); - // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder - // with order cache + fetchOpenOrders - // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX - return this.parseOrders (response, market, since, limit); + if (limit !== undefined) { + request['limit'] = limit; // default = 300 + } + const orderbook = await this.publicGetDepth (this.extend (request, params)); + const timestamp = this.safeTimestamp (orderbook, 'timestamp'); + return this.parseOrderBook (orderbook, timestamp); + } + + parseTicker (ticker, market = undefined) { + const timestamp = this.safeTimestamp (ticker, 'at'); + ticker = ticker['ticker']; + let symbol = undefined; + if (market) { + symbol = market['symbol']; + } + const last = this.safeNumber (ticker, 'last'); + return { + 'symbol': symbol, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'bidVolume': undefined, + 'ask': this.safeNumber (ticker, 'sell'), + 'askVolume': undefined, + 'vwap': undefined, + 'open': this.safeNumber (ticker, 'open'), + 'close': last, + 'last': last, + 'previousClose': undefined, + 'change': undefined, + 'percentage': undefined, + 'average': undefined, + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': undefined, + 'info': ticker, + }; + } + + async fetchTickers (symbols = undefined, params = {}) { + await this.loadMarkets (); + const response = await this.publicGetTickers (params); + const ids = Object.keys (response); + const result = {}; + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + let market = undefined; + let symbol = id; + if (id in this.markets_by_id) { + market = this.markets_by_id[id]; + symbol = market['symbol']; + } else { + let base = id.slice (0, 3); + let quote = id.slice (3, 6); + base = base.toUpperCase (); + quote = quote.toUpperCase (); + base = this.safeCurrencyCode (base); + quote = this.safeCurrencyCode (quote); + symbol = base + '/' + quote; + } + result[symbol] = this.parseTicker (response[id], market); + } + return this.filterByArray (result, 'symbol', symbols); + } + + async fetchTicker (symbol, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTickersMarket (this.extend (request, params)); + return this.parseTicker (response, market); + } + + async fetchL3OrderBook (symbol, limit = undefined, params = {}) { + return await this.fetchOrderBook (symbol, limit, params); + } + + async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.publicGetTrades (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); } parseTrade (trade, market = undefined) { @@ -148,9 +289,14 @@ module.exports = class kuna extends acx { }; side = this.safeString (sideMap, side, side); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const orderId = this.safeString (trade, 'order_id'); const id = this.safeString (trade, 'id'); return { @@ -170,29 +316,6 @@ module.exports = class kuna extends acx { }; } - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.publicGetTrades (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - - async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { - if (symbol === undefined) { - throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); - } - await this.loadMarkets (); - const market = this.market (symbol); - const request = { - 'market': market['id'], - }; - const response = await this.privateGetTradesMy (this.extend (request, params)); - return this.parseTrades (response, market, since, limit); - } - async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const trades = await this.fetchTrades (symbol, since, limit, params); @@ -211,4 +334,198 @@ module.exports = class kuna extends acx { } return result; } + + async fetchBalance (params = {}) { + await this.loadMarkets (); + const response = await this.privateGetMembersMe (params); + const balances = this.safeValue (response, 'accounts'); + const result = { 'info': balances }; + for (let i = 0; i < balances.length; i++) { + const balance = balances[i]; + const currencyId = this.safeString (balance, 'currency'); + const code = this.safeCurrencyCode (currencyId); + const account = this.account (); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); + result[code] = account; + } + return this.parseBalance (result, false); + } + + async createOrder (symbol, type, side, amount, price = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'market': this.marketId (symbol), + 'side': side, + 'volume': amount.toString (), + 'ord_type': type, + }; + if (type === 'limit') { + request['price'] = price.toString (); + } + const response = await this.privatePostOrders (this.extend (request, params)); + const marketId = this.safeValue (response, 'market'); + const market = this.safeValue (this.markets_by_id, marketId); + return this.parseOrder (response, market); + } + + async cancelOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': id, + }; + const response = await this.privatePostOrderDelete (this.extend (request, params)); + const order = this.parseOrder (response); + const status = order['status']; + if (status === 'closed' || status === 'canceled') { + throw new OrderNotFound (this.id + ' ' + this.json (order)); + } + return order; + } + + parseOrderStatus (status) { + const statuses = { + 'done': 'closed', + 'wait': 'open', + 'cancel': 'canceled', + }; + return this.safeString (statuses, status, status); + } + + parseOrder (order, market = undefined) { + const marketId = this.safeString (order, 'market'); + const symbol = this.safeSymbol (marketId, market); + const timestamp = this.parse8601 (this.safeString (order, 'created_at')); + const status = this.parseOrderStatus (this.safeString (order, 'state')); + const type = this.safeString (order, 'type'); + const side = this.safeString (order, 'side'); + const id = this.safeString (order, 'id'); + return this.safeOrder ({ + 'id': id, + 'clientOrderId': undefined, + 'timestamp': timestamp, + 'datetime': this.iso8601 (timestamp), + 'lastTradeTimestamp': undefined, + 'status': status, + 'symbol': symbol, + 'type': type, + 'timeInForce': undefined, + 'postOnly': undefined, + 'side': side, + 'price': this.safeNumber (order, 'price'), + 'stopPrice': undefined, + 'amount': this.safeNumber (order, 'volume'), + 'filled': this.safeNumber (order, 'executed_volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'trades': undefined, + 'fee': undefined, + 'info': order, + 'cost': undefined, + 'average': undefined, + }); + } + + async fetchOrder (id, symbol = undefined, params = {}) { + await this.loadMarkets (); + const request = { + 'id': parseInt (id), + }; + const response = await this.privateGetOrder (this.extend (request, params)); + return this.parseOrder (response); + } + + async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetOrders (this.extend (request, params)); + // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder + // with order cache + fetchOpenOrders + // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX + return this.parseOrders (response, market, since, limit); + } + + async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { + if (symbol === undefined) { + throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); + } + await this.loadMarkets (); + const market = this.market (symbol); + const request = { + 'market': market['id'], + }; + const response = await this.privateGetTradesMy (this.extend (request, params)); + return this.parseTrades (response, market, since, limit); + } + + nonce () { + return this.milliseconds (); + } + + encodeParams (params) { + if ('orders' in params) { + const orders = params['orders']; + let query = this.urlencode (this.keysort (this.omit (params, 'orders'))); + for (let i = 0; i < orders.length; i++) { + const order = orders[i]; + const keys = Object.keys (order); + for (let k = 0; k < keys.length; k++) { + const key = keys[k]; + const value = order[key]; + query += '&orders%5B%5D%5B' + key + '%5D=' + value.toString (); + } + } + return query; + } + return this.urlencode (this.keysort (params)); + } + + sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { + let request = '/api/' + this.version + '/' + this.implodeParams (path, params); + if ('extension' in this.urls) { + request += this.urls['extension']; + } + const query = this.omit (params, this.extractParams (path)); + let url = this.urls['api'] + request; + if (api === 'public') { + if (Object.keys (query).length) { + url += '?' + this.urlencode (query); + } + } else { + this.checkRequiredCredentials (); + const nonce = this.nonce ().toString (); + const query = this.encodeParams (this.extend ({ + 'access_key': this.apiKey, + 'tonce': nonce, + }, params)); + const auth = method + '|' + request + '|' + query; + const signed = this.hmac (this.encode (auth), this.encode (this.secret)); + const suffix = query + '&signature=' + signed; + if (method === 'GET') { + url += '?' + suffix; + } else { + body = suffix; + headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; + } + } + return { 'url': url, 'method': method, 'body': body, 'headers': headers }; + } + + handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) { + if (response === undefined) { + return; + } + if (code === 400) { + const error = this.safeValue (response, 'error'); + const errorCode = this.safeString (error, 'code'); + const feedback = this.id + ' ' + this.json (response); + this.throwExactlyMatchedException (this.exceptions, errorCode, feedback); + // fallback to default error handler + } + } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lakebtc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lakebtc.js index 8acd8cc41..991e6ff86 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lakebtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lakebtc.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -112,10 +113,10 @@ module.exports = class lakebtc extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balances, currencyId); + account['total'] = this.safeString (balances, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -133,16 +134,16 @@ module.exports = class lakebtc extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -152,7 +153,7 @@ module.exports = class lakebtc extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -183,14 +184,11 @@ module.exports = class lakebtc extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/latoken.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/latoken.js index 45cb5951d..ecc53a8c6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/latoken.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/latoken.js @@ -4,7 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, DDoSProtection, BadRequest, AuthenticationError } = require ('./base/errors'); -const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -85,6 +85,7 @@ module.exports = class latoken extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'maker': 0.1 / 100, @@ -169,7 +170,7 @@ module.exports = class latoken extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minQty'), + 'min': this.safeNumber (market, 'minQty'), 'max': undefined, }, 'price': { @@ -219,7 +220,7 @@ module.exports = class latoken extends Exchange { const numericId = this.safeInteger (currency, 'currencyId'); const code = this.safeCurrencyCode (id); const precision = this.safeInteger (currency, 'precission'); - const fee = this.safeFloat (currency, 'fee'); + const fee = this.safeNumber (currency, 'fee'); const active = undefined; result[code] = { 'id': id, @@ -253,27 +254,6 @@ module.exports = class latoken extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = amount * rate; - let precision = market['precision']['price']; - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - precision = market['precision']['amount']; - } - cost = this.decimalToPrecision (cost, ROUND, precision, this.precisionMode); - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (cost), - }; - } - async fetchBalance (params = {}) { await this.loadMarkets (); const response = await this.privateGetAccountBalances (params); @@ -297,17 +277,15 @@ module.exports = class latoken extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); - const frozen = this.safeFloat (balance, 'frozen'); - const pending = this.safeFloat (balance, 'pending'); - const used = this.sum (frozen, pending); - const account = { - 'free': this.safeFloat (balance, 'available'), - 'used': used, - 'total': this.safeFloat (balance, 'amount'), - }; + const frozen = this.safeString (balance, 'frozen'); + const pending = this.safeString (balance, 'pending'); + const account = this.account (); + account['used'] = Precise.stringAdd (frozen, pending); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -352,20 +330,20 @@ module.exports = class latoken extends Exchange { // const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const open = this.safeFloat (ticker, 'open'); - const close = this.safeFloat (ticker, 'close'); + const open = this.safeNumber (ticker, 'open'); + const close = this.safeNumber (ticker, 'close'); let change = undefined; if (open !== undefined && close !== undefined) { change = close - open; } - const percentage = this.safeFloat (ticker, 'priceChange'); + const percentage = this.safeNumber (ticker, 'priceChange'); const timestamp = this.nonce (); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'low': this.safeFloat (ticker, 'low'), - 'high': this.safeFloat (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -379,7 +357,7 @@ module.exports = class latoken extends Exchange { 'percentage': percentage, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -463,22 +441,19 @@ module.exports = class latoken extends Exchange { timestamp *= 1000; } } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'orderId'); - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -613,29 +588,17 @@ module.exports = class latoken extends Exchange { const symbol = this.safeSymbol (marketId, market); const side = this.safeString (order, 'side'); const type = this.safeString (order, 'orderType'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - const filled = this.safeFloat (order, 'executedAmount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); + const filled = this.safeNumber (order, 'executedAmount'); const status = this.parseOrderStatus (this.safeString (order, 'orderStatus')); - let cost = undefined; - if (filled !== undefined) { - if (price !== undefined) { - cost = filled * price; - } - } const timeFilled = this.safeTimestamp (order, 'timeFilled'); let lastTradeTimestamp = undefined; if ((timeFilled !== undefined) && (timeFilled > 0)) { lastTradeTimestamp = timeFilled; } const clientOrderId = this.safeString (order, 'cliOrdId'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -650,14 +613,14 @@ module.exports = class latoken extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, 'average': undefined, - 'remaining': remaining, + 'remaining': undefined, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lbank.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lbank.js index 9b39a0236..e9e4658dc 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lbank.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lbank.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -201,8 +202,8 @@ module.exports = class lbank extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const info = ticker; ticker = info['ticker']; - const last = this.safeFloat (ticker, 'latest'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'latest'); + const percentage = this.safeNumber (ticker, 'change'); let open = undefined; if (percentage !== undefined) { const relativeChange = this.sum (1, percentage / 100); @@ -223,8 +224,8 @@ module.exports = class lbank extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -237,8 +238,8 @@ module.exports = class lbank extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'vol'), - 'quoteVolume': this.safeFloat (ticker, 'turnover'), + 'baseVolume': this.safeNumber (ticker, 'vol'), + 'quoteVolume': this.safeNumber (ticker, 'turnover'), 'info': info, }; } @@ -288,17 +289,15 @@ module.exports = class lbank extends Exchange { symbol = market['symbol']; } const timestamp = this.safeInteger (trade, 'date_ms'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = parseFloat (this.costToPrecision (symbol, price * amount)); - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'tid'); const type = undefined; - const side = this.safeString (trade, 'type'); + let side = this.safeString (trade, 'type'); + side = side.replace ('_market', ''); return { 'id': id, 'info': this.safeValue (trade, 'info', trade), @@ -346,11 +345,11 @@ module.exports = class lbank extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -415,12 +414,12 @@ module.exports = class lbank extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['used'] = this.safeFloat (freeze, currencyId); - account['total'] = this.safeFloat (asset, currencyId); + account['free'] = this.safeString (free, currencyId); + account['used'] = this.safeString (freeze, currencyId); + account['total'] = this.safeString (asset, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -448,35 +447,20 @@ module.exports = class lbank extends Exchange { // "status":2 // } // - let symbol = undefined; - const responseMarket = this.safeValue (this.marketsById, order['symbol']); - if (responseMarket !== undefined) { - symbol = responseMarket['symbol']; - } else if (market !== undefined) { - symbol = market['symbol']; - } + const marketId = this.safeString (order, 'symbol'); + const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeInteger (order, 'create_time'); // Limit Order Request Returns: Order Price // Market Order Returns: cny amount of market order - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount', 0.0); - const filled = this.safeFloat (order, 'deal_amount', 0.0); - const av_price = this.safeFloat (order, 'avg_price'); - let cost = undefined; - if (av_price !== undefined) { - cost = filled * av_price; - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount', 0.0); + const filled = this.safeNumber (order, 'deal_amount', 0.0); + const average = this.safeNumber (order, 'avg_price'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const id = this.safeString (order, 'order_id'); const type = this.safeString (order, 'order_type'); const side = this.safeString (order, 'type'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -490,15 +474,15 @@ module.exports = class lbank extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': undefined, 'info': this.safeValue (order, 'info', order), - 'average': undefined, - }; + 'average': average, + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/liquid.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/liquid.js index 732eda853..0365ef102 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/liquid.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/liquid.js @@ -4,7 +4,8 @@ const Exchange = require ('./base/Exchange'); const { TICK_SIZE } = require ('./base/functions/number'); -const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported } = require ('./base/errors'); +const { ExchangeError, ArgumentsRequired, InvalidNonce, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError, DDoSProtection, NotSupported, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -108,7 +109,7 @@ module.exports = class liquid extends Exchange { 'trading': { 'tierBased': true, 'percentage': true, - 'taker': 0.0015, + 'taker': 0.0030, 'maker': 0.0000, 'tiers': { 'perpetual': { @@ -127,48 +128,52 @@ module.exports = class liquid extends Exchange { [ 300000000, -0.00025 ], ], 'taker': [ - [ 0, 0.000600 ], - [ 25000, 0.000575 ], - [ 50000, 0.000550 ], - [ 100000, 0.000525 ], - [ 1000000, 0.000500 ], - [ 10000000, 0.000475 ], - [ 25000000, 0.000450 ], - [ 50000000, 0.000425 ], - [ 75000000, 0.000400 ], - [ 100000000, 0.000375 ], - [ 200000000, 0.000350 ], - [ 300000000, 0.000325 ], + [ 0, 0.00120 ], + [ 25000, 0.00115 ], + [ 50000, 0.00110 ], + [ 100000, 0.00105 ], + [ 1000000, 0.00100 ], + [ 10000000, 0.00095 ], + [ 25000000, 0.00090 ], + [ 50000000, 0.00085 ], + [ 75000000, 0.00080 ], + [ 100000000, 0.00075 ], + [ 200000000, 0.00070 ], + [ 300000000, 0.00065 ], ], }, 'spot': { 'taker': [ - [ 0, 0.0015 ], - [ 10000, 0.0015 ], - [ 20000, 0.0014 ], - [ 50000, 0.0013 ], - [ 100000, 0.0010 ], - [ 1000000, 0.0008 ], - [ 5000000, 0.0006 ], - [ 10000000, 0.0005 ], - [ 25000000, 0.0005 ], - [ 50000000, 0.00045 ], - [ 100000000, 0.0004 ], - [ 200000000, 0.0003 ], + [ 0, 0.003 ], + [ 10000, 0.0029 ], + [ 20000, 0.0028 ], + [ 50000, 0.0026 ], + [ 100000, 0.0020 ], + [ 1000000, 0.0016 ], + [ 5000000, 0.0012 ], + [ 10000000, 0.0010 ], + [ 25000000, 0.0009 ], + [ 50000000, 0.0008 ], + [ 100000000, 0.0007 ], + [ 200000000, 0.0006 ], + [ 500000000, 0.0004 ], + [ 1000000000, 0.0003 ], ], 'maker': [ [ 0, 0.0000 ], - [ 10000, 0.0015 ], - [ 20000, 0.1400 ], - [ 50000, 0.1300 ], - [ 100000, 0.0800 ], - [ 1000000, 0.0004 ], - [ 5000000, 0.00035 ], - [ 10000000, 0.00025 ], + [ 10000, 0.0020 ], + [ 20000, 0.0019 ], + [ 50000, 0.0018 ], + [ 100000, 0.0016 ], + [ 1000000, 0.0008 ], + [ 5000000, 0.0007 ], + [ 10000000, 0.0005 ], [ 25000000, 0.0000 ], [ 50000000, 0.0000 ], [ 100000000, 0.0000 ], [ 200000000, 0.0000 ], + [ 500000000, 0.0000 ], + [ 1000000000, 0.0000 ], ], }, }, @@ -187,6 +192,7 @@ module.exports = class liquid extends Exchange { 'less_than_order_size': InvalidOrder, 'price_too_high': InvalidOrder, 'price_too_small': InvalidOrder, // {"errors":{"order":["price_too_small"]}} + 'product_disabled': BadSymbol, // {"errors":{"order":["product_disabled"]}} }, 'commonCurrencies': { 'WIN': 'WCOIN', @@ -236,7 +242,7 @@ module.exports = class liquid extends Exchange { 'info': currency, 'name': code, 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': decimalPrecision, 'limits': { 'amount': { @@ -252,7 +258,7 @@ module.exports = class liquid extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal'), + 'min': this.safeNumber (currency, 'minimum_withdrawal'), 'max': undefined, }, }, @@ -377,19 +383,19 @@ module.exports = class liquid extends Exchange { let maker = this.fees['trading']['maker']; let taker = this.fees['trading']['taker']; if (type === 'swap') { - maker = this.safeFloat (market, 'maker_fee', this.fees['trading']['maker']); - taker = this.safeFloat (market, 'taker_fee', this.fees['trading']['taker']); + maker = this.safeNumber (market, 'maker_fee', this.fees['trading']['maker']); + taker = this.safeNumber (market, 'taker_fee', this.fees['trading']['taker']); } const disabled = this.safeValue (market, 'disabled', false); const active = !disabled; const baseCurrency = this.safeValue (currenciesByCode, base); const precision = { 'amount': 0.00000001, - 'price': this.safeFloat (market, 'tick_size'), + 'price': this.safeNumber (market, 'tick_size'), }; let minAmount = undefined; if (baseCurrency !== undefined) { - minAmount = this.safeFloat (baseCurrency['info'], 'minimum_order_quantity'); + minAmount = this.safeNumber (baseCurrency['info'], 'minimum_order_quantity'); } const limits = { 'amount': { @@ -471,8 +477,8 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } for (let i = 0; i < fiat.length; i++) { @@ -480,11 +486,11 @@ module.exports = class liquid extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'reserved_balance'); + account['total'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'reserved_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -503,7 +509,7 @@ module.exports = class liquid extends Exchange { if (ticker['last_traded_price']) { const length = ticker['last_traded_price'].length; if (length > 0) { - last = this.safeFloat (ticker, 'last_traded_price'); + last = this.safeNumber (ticker, 'last_traded_price'); } } } @@ -528,7 +534,7 @@ module.exports = class liquid extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.safeFloat (ticker, 'last_price_24h'); + const open = this.safeNumber (ticker, 'last_price_24h'); if (open !== undefined && last !== undefined) { change = last - open; average = this.sum (last, open) / 2; @@ -540,11 +546,11 @@ module.exports = class liquid extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_market_ask'), - 'low': this.safeFloat (ticker, 'low_market_bid'), - 'bid': this.safeFloat (ticker, 'market_bid'), + 'high': this.safeNumber (ticker, 'high_market_ask'), + 'low': this.safeNumber (ticker, 'low_market_bid'), + 'bid': this.safeNumber (ticker, 'market_bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'market_ask'), + 'ask': this.safeNumber (ticker, 'market_ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -554,7 +560,7 @@ module.exports = class liquid extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'volume_24h'), 'quoteVolume': undefined, 'info': ticker, }; @@ -600,14 +606,11 @@ module.exports = class liquid extends Exchange { if (mySide !== undefined) { takerOrMaker = (takerSide === mySide) ? 'taker' : 'maker'; } - let cost = undefined; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { @@ -810,9 +813,9 @@ module.exports = class liquid extends Exchange { const marketId = this.safeString (order, 'product_id'); market = this.safeValue (this.markets_by_id, marketId); const status = this.parseOrderStatus (this.safeString (order, 'status')); - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'filled_quantity'); - const price = this.safeFloat (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + let filled = this.safeNumber (order, 'filled_quantity'); + const price = this.safeNumber (order, 'price'); let symbol = undefined; let feeCurrency = undefined; if (market !== undefined) { @@ -822,7 +825,7 @@ module.exports = class liquid extends Exchange { const type = this.safeString (order, 'order_type'); let tradeCost = 0; let tradeFilled = 0; - let average = this.safeFloat (order, 'average_price'); + let average = this.safeNumber (order, 'average_price'); const trades = this.parseTrades (this.safeValue (order, 'executions', []), market, undefined, undefined, { 'order': orderId, 'type': type, @@ -879,7 +882,7 @@ module.exports = class liquid extends Exchange { 'trades': trades, 'fee': { 'currency': feeCurrency, - 'cost': this.safeFloat (order, 'order_fee'), + 'cost': this.safeNumber (order, 'order_fee'), }, 'info': order, }; @@ -1034,7 +1037,7 @@ module.exports = class liquid extends Exchange { const updated = this.safeTimestamp (transaction, 'updated_at'); const type = 'withdrawal'; const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); return { 'info': transaction, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/luno.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/luno.js index 2bbec0ec1..ad5568218 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/luno.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/luno.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -79,6 +80,10 @@ module.exports = class luno extends Exchange { 'quotes/{id}', 'withdrawals', 'withdrawals/{id}', + 'transfers', + // GET /api/exchange/2/listorders + // GET /api/exchange/2/orders/{id} + // GET /api/exchange/3/order ], 'post': [ 'accounts', @@ -153,12 +158,12 @@ module.exports = class luno extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_volume'), - 'max': this.safeFloat (market, 'max_volume'), + 'min': this.safeNumber (market, 'min_volume'), + 'max': this.safeNumber (market, 'max_volume'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': undefined, @@ -209,20 +214,22 @@ module.exports = class luno extends Exchange { const wallet = wallets[i]; const currencyId = this.safeString (wallet, 'asset'); const code = this.safeCurrencyCode (currencyId); - const reserved = this.safeFloat (wallet, 'reserved'); - const unconfirmed = this.safeFloat (wallet, 'unconfirmed'); - const balance = this.safeFloat (wallet, 'balance'); + const reserved = this.safeString (wallet, 'reserved'); + const unconfirmed = this.safeString (wallet, 'unconfirmed'); + const balance = this.safeString (wallet, 'balance'); + const reservedUnconfirmed = Precise.stringAdd (reserved, unconfirmed); + const balanceUnconfirmed = Precise.stringAdd (balance, unconfirmed); if (code in result) { - result[code]['used'] = this.sum (result[code]['used'], reserved, unconfirmed); - result[code]['total'] = this.sum (result[code]['total'], balance, unconfirmed); + result[code]['used'] = Precise.stringAdd (result[code]['used'], reservedUnconfirmed); + result[code]['total'] = Precise.stringAdd (result[code]['total'], balanceUnconfirmed); } else { const account = this.account (); - account['used'] = this.sum (reserved, unconfirmed); - account['total'] = this.sum (balance, unconfirmed); + account['used'] = reservedUnconfirmed; + account['total'] = balanceUnconfirmed; result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -273,18 +280,12 @@ module.exports = class luno extends Exchange { const side = (order['type'] === 'ASK') ? 'sell' : 'buy'; const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'limit_price'); - const amount = this.safeFloat (order, 'limit_volume'); - const quoteFee = this.safeFloat (order, 'fee_counter'); - const baseFee = this.safeFloat (order, 'fee_base'); - const filled = this.safeFloat (order, 'base'); - const cost = this.safeFloat (order, 'counter'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } + const price = this.safeNumber (order, 'limit_price'); + const amount = this.safeNumber (order, 'limit_volume'); + const quoteFee = this.safeNumber (order, 'fee_counter'); + const baseFee = this.safeNumber (order, 'fee_base'); + const filled = this.safeNumber (order, 'base'); + const cost = this.safeNumber (order, 'counter'); const fee = { 'currency': undefined }; if (quoteFee) { fee['cost'] = quoteFee; @@ -298,7 +299,7 @@ module.exports = class luno extends Exchange { } } const id = this.safeString (order, 'order_id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'datetime': this.iso8601 (timestamp), @@ -315,12 +316,12 @@ module.exports = class luno extends Exchange { 'amount': amount, 'filled': filled, 'cost': cost, - 'remaining': remaining, + 'remaining': undefined, 'trades': undefined, 'fee': fee, 'info': order, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -366,16 +367,16 @@ module.exports = class luno extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last_trade'); + const last = this.safeNumber (ticker, 'last_trade'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -385,7 +386,7 @@ module.exports = class luno extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'rolling_24_hour_volume'), + 'baseVolume': this.safeNumber (ticker, 'rolling_24_hour_volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -436,8 +437,8 @@ module.exports = class luno extends Exchange { } else { side = trade['is_buy'] ? 'buy' : 'sell'; } - const feeBase = this.safeFloat (trade, 'fee_base'); - const feeCounter = this.safeFloat (trade, 'fee_counter'); + const feeBase = this.safeNumber (trade, 'fee_base'); + const feeCounter = this.safeNumber (trade, 'fee_counter'); let feeCurrency = undefined; let feeCost = undefined; if (feeBase !== undefined) { @@ -462,10 +463,10 @@ module.exports = class luno extends Exchange { 'type': undefined, 'side': side, 'takerOrMaker': takerOrMaker, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), // Does not include potential fee costs - 'cost': this.safeFloat (trade, 'counter'), + 'cost': this.safeNumber (trade, 'counter'), 'fee': { 'cost': feeCost, 'currency': feeCurrency, @@ -512,8 +513,8 @@ module.exports = class luno extends Exchange { const response = await this.privateGetFeeInfo (params); return { 'info': response, - 'maker': this.safeFloat (response, 'maker_fee'), - 'taker': this.safeFloat (response, 'taker_fee'), + 'maker': this.safeNumber (response, 'maker_fee'), + 'taker': this.safeNumber (response, 'taker_fee'), }; } @@ -647,9 +648,9 @@ module.exports = class luno extends Exchange { const timestamp = this.safeValue (entry, 'timestamp'); const currencyId = this.safeString (entry, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); - const available_delta = this.safeFloat (entry, 'available_delta'); - const balance_delta = this.safeFloat (entry, 'balance_delta'); - const after = this.safeFloat (entry, 'balance'); + const available_delta = this.safeNumber (entry, 'available_delta'); + const balance_delta = this.safeNumber (entry, 'balance_delta'); + const after = this.safeNumber (entry, 'balance'); const comment = this.safeString (entry, 'description'); let before = after; let amount = 0.0; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lykke.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lykke.js index edc0fe73a..707034d20 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lykke.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/lykke.js @@ -3,6 +3,7 @@ // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -184,18 +185,16 @@ module.exports = class lykke extends Exchange { const id = this.safeString2 (trade, 'id', 'Id'); const orderId = this.safeString (trade, 'OrderId'); const timestamp = this.parse8601 (this.safeString2 (trade, 'dateTime', 'DateTime')); - const price = this.safeFloat2 (trade, 'price', 'Price'); - let amount = this.safeFloat2 (trade, 'volume', 'Amount'); + const priceString = this.safeString2 (trade, 'price', 'Price'); + let amountString = this.safeString2 (trade, 'volume', 'Amount'); let side = this.safeStringLower (trade, 'action'); if (side === undefined) { - if (amount < 0) { - side = 'sell'; - } else { - side = 'buy'; - } + side = (amountString[0] === '-') ? 'sell' : 'buy'; } - amount = Math.abs (amount); - const cost = price * amount; + amountString = (amountString[0] === '-') ? amountString.slice (1) : amountString; + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const fee = { 'cost': 0, // There are no fees for trading. https://www.lykke.com/wallet-fees-and-limits/ 'currency': market['quote'], @@ -256,11 +255,11 @@ module.exports = class lykke extends Exchange { const currencyId = this.safeString (balance, 'AssetId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Balance'); - account['used'] = this.safeFloat (balance, 'Reserved'); + account['total'] = this.safeString (balance, 'Balance'); + account['used'] = this.safeString (balance, 'Reserved'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -307,7 +306,7 @@ module.exports = class lykke extends Exchange { // } // const id = this.safeString (result, 'Id'); - price = this.safeFloat (result, 'Price'); + price = this.safeNumber (result, 'Price'); return { 'id': id, 'info': result, @@ -398,16 +397,16 @@ module.exports = class lykke extends Exchange { if (market) { symbol = market['symbol']; } - const close = this.safeFloat (ticker, 'lastPrice'); + const close = this.safeNumber (ticker, 'lastPrice'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'bid'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -418,7 +417,7 @@ module.exports = class lykke extends Exchange { 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, - 'quoteVolume': this.safeFloat (ticker, 'volume24H'), + 'quoteVolume': this.safeNumber (ticker, 'volume24H'), 'info': ticker, }; } @@ -476,20 +475,18 @@ module.exports = class lykke extends Exchange { } else if (('CreatedAt' in order) && (order['CreatedAt'])) { timestamp = this.parse8601 (order['CreatedAt']); } - const price = this.safeFloat (order, 'Price'); + const price = this.safeNumber (order, 'Price'); let side = undefined; - let amount = this.safeFloat (order, 'Volume'); + let amount = this.safeNumber (order, 'Volume'); if (amount < 0) { side = 'sell'; amount = Math.abs (amount); } else { side = 'buy'; } - const remaining = Math.abs (this.safeFloat (order, 'RemainingVolume')); - const filled = amount - remaining; - const cost = filled * price; + const remaining = Math.abs (this.safeNumber (order, 'RemainingVolume')); const id = this.safeString (order, 'Id'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -503,15 +500,15 @@ module.exports = class lykke extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'amount': amount, - 'filled': filled, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -572,8 +569,8 @@ module.exports = class lykke extends Exchange { } parseBidAsk (bidask, priceKey = 0, amountKey = 1) { - const price = this.safeFloat (bidask, priceKey); - let amount = this.safeFloat (bidask, amountKey); + const price = this.safeNumber (bidask, priceKey); + let amount = this.safeNumber (bidask, amountKey); if (amount < 0) { amount = -amount; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mercado.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mercado.js index a2fd9593e..2746e14b8 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mercado.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mercado.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -160,7 +161,7 @@ module.exports = class mercado extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, baseId), + 'min': this.safeNumber (amountLimits, baseId), 'max': undefined, }, 'price': { @@ -196,16 +197,16 @@ module.exports = class mercado extends Exchange { const response = await this.publicGetCoinTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'ticker', {}); const timestamp = this.safeTimestamp (ticker, 'date'); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -215,7 +216,7 @@ module.exports = class mercado extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -230,15 +231,12 @@ module.exports = class mercado extends Exchange { const id = this.safeString2 (trade, 'tid', 'operation_id'); const type = undefined; const side = this.safeString (trade, 'type'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } - const feeCost = this.safeFloat (trade, 'fee_rate'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const feeCost = this.safeNumber (trade, 'fee_rate'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -295,12 +293,12 @@ module.exports = class mercado extends Exchange { if (currencyId in balances) { const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['total'] = this.safeFloat (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -407,32 +405,31 @@ module.exports = class mercado extends Exchange { // } // const id = this.safeString (order, 'order_id'); + const order_type = this.safeString (order, 'order_type'); let side = undefined; if ('order_type' in order) { - side = (order['order_type'] === 1) ? 'buy' : 'sell'; + side = (order_type === '1') ? 'buy' : 'sell'; } const status = this.parseOrderStatus (this.safeString (order, 'status')); const marketId = this.safeString (order, 'coin_pair'); market = this.safeMarket (marketId, market); const timestamp = this.safeTimestamp (order, 'created_timestamp'); const fee = { - 'cost': this.safeFloat (order, 'fee'), + 'cost': this.safeNumber (order, 'fee'), 'currency': market['quote'], }; - const price = this.safeFloat (order, 'limit_price'); - // price = this.safeFloat (order, 'executed_price_avg', price); - const average = this.safeFloat (order, 'executed_price_avg'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'executed_quantity'); - const remaining = amount - filled; - const cost = filled * average; + const price = this.safeNumber (order, 'limit_price'); + // price = this.safeNumber (order, 'executed_price_avg', price); + const average = this.safeNumber (order, 'executed_price_avg'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const lastTradeTimestamp = this.safeTimestamp (order, 'updated_timestamp'); const rawTrades = this.safeValue (order, 'operations', []); const trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'side': side, 'order': id, }); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -446,15 +443,15 @@ module.exports = class mercado extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'average': average, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': trades, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { @@ -512,11 +509,11 @@ module.exports = class mercado extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeTimestamp (ohlcv, 'timestamp'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mixcoins.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mixcoins.js index 85138f138..11bbf93b6 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mixcoins.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/mixcoins.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -72,11 +73,11 @@ module.exports = class mixcoins extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (balances, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'avail'); - account['used'] = this.safeFloat (balance, 'lock'); + account['free'] = this.safeString (balance, 'avail'); + account['used'] = this.safeString (balance, 'lock'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -96,16 +97,16 @@ module.exports = class mixcoins extends Exchange { const response = await this.publicGetTicker (this.extend (request, params)); const ticker = this.safeValue (response, 'result'); const timestamp = this.milliseconds (); - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -115,7 +116,7 @@ module.exports = class mixcoins extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -128,14 +129,11 @@ module.exports = class mixcoins extends Exchange { symbol = market['symbol']; } const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'id': id, 'info': trade, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ndax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ndax.js index 0367c2695..37e8b2760 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ndax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ndax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -244,7 +245,7 @@ module.exports = class ndax extends Exchange { const name = this.safeString (currency, 'ProductFullName'); const type = this.safeString (currency, 'ProductType'); const code = this.safeCurrencyCode (this.safeString (currency, 'Product')); - const precision = this.safeFloat (currency, 'TickSize'); + const precision = this.safeNumber (currency, 'TickSize'); const isDisabled = this.safeValue (currency, 'IsDisabled'); const active = !isDisabled; result[code] = { @@ -325,8 +326,8 @@ module.exports = class ndax extends Exchange { const quote = this.safeCurrencyCode (this.safeString (market, 'Product2Symbol')); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'QuantityIncrement'), - 'price': this.safeFloat (market, 'PriceIncrement'), + 'amount': this.safeNumber (market, 'QuantityIncrement'), + 'price': this.safeNumber (market, 'PriceIncrement'), }; const sessionStatus = this.safeString (market, 'SessionStatus'); const isDisable = this.safeValue (market, 'IsDisable'); @@ -344,11 +345,11 @@ module.exports = class ndax extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'MinimumQuantity'), + 'min': this.safeNumber (market, 'MinimumQuantity'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'MinimumPrice'), + 'min': this.safeNumber (market, 'MinimumPrice'), 'max': undefined, }, 'cost': { @@ -469,27 +470,27 @@ module.exports = class ndax extends Exchange { const timestamp = this.safeInteger (ticker, 'TimeStamp'); const marketId = this.safeString (ticker, 'InstrumentId'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'LastTradedPx'); - const percentage = this.safeFloat (ticker, 'Rolling24HrPxChangePercent'); - const change = this.safeFloat (ticker, 'Rolling24HrPxChange'); - const open = this.safeFloat (ticker, 'SessionOpen'); + const last = this.safeNumber (ticker, 'LastTradedPx'); + const percentage = this.safeNumber (ticker, 'Rolling24HrPxChangePercent'); + const change = this.safeNumber (ticker, 'Rolling24HrPxChange'); + const open = this.safeNumber (ticker, 'SessionOpen'); let average = undefined; if ((last !== undefined) && (change !== undefined)) { average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'Rolling24HrVolume'); - const quoteVolume = this.safeFloat (ticker, 'Rolling24HrNotional'); + const baseVolume = this.safeNumber (ticker, 'Rolling24HrVolume'); + const quoteVolume = this.safeNumber (ticker, 'Rolling24HrNotional'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'SessionHigh'), - 'low': this.safeFloat (ticker, 'SessionLow'), - 'bid': this.safeFloat (ticker, 'BestBid'), - 'bidVolume': undefined, // this.safeFloat (ticker, 'BidQty'), always shows 0 - 'ask': this.safeFloat (ticker, 'BestOffer'), - 'askVolume': undefined, // this.safeFloat (ticker, 'AskQty'), always shows 0 + 'high': this.safeNumber (ticker, 'SessionHigh'), + 'low': this.safeNumber (ticker, 'SessionLow'), + 'bid': this.safeNumber (ticker, 'BestBid'), + 'bidVolume': undefined, // this.safeNumber (ticker, 'BidQty'), always shows 0 + 'ask': this.safeNumber (ticker, 'BestOffer'), + 'askVolume': undefined, // this.safeNumber (ticker, 'AskQty'), always shows 0 'vwap': vwap, 'open': open, 'close': last, @@ -562,11 +563,11 @@ module.exports = class ndax extends Exchange { // return [ this.safeInteger (ohlcv, 0), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -714,8 +715,8 @@ module.exports = class ndax extends Exchange { // "OMSId":1 // } // - let price = undefined; - let amount = undefined; + let priceString = undefined; + let amountString = undefined; let cost = undefined; let timestamp = undefined; let id = undefined; @@ -726,11 +727,8 @@ module.exports = class ndax extends Exchange { let fee = undefined; let type = undefined; if (Array.isArray (trade)) { - price = this.safeFloat (trade, 3); - amount = this.safeFloat (trade, 2); - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + priceString = this.safeString (trade, 3); + amountString = this.safeString (trade, 2); timestamp = this.safeInteger (trade, 6); id = this.safeString (trade, 0); marketId = this.safeInteger (trade, 1); @@ -742,13 +740,13 @@ module.exports = class ndax extends Exchange { id = this.safeString (trade, 'TradeId'); orderId = this.safeString2 (trade, 'OrderId', 'OrigOrderId'); marketId = this.safeString2 (trade, 'InstrumentId', 'Instrument'); - price = this.safeFloat (trade, 'Price'); - amount = this.safeFloat (trade, 'Quantity'); - cost = this.safeFloat2 (trade, 'Value', 'GrossValueExecuted'); + priceString = this.safeString (trade, 'Price'); + amountString = this.safeString (trade, 'Quantity'); + cost = this.safeNumber2 (trade, 'Value', 'GrossValueExecuted'); takerOrMaker = this.safeStringLower (trade, 'MakerTaker'); side = this.safeStringLower (trade, 'Side'); type = this.safeStringLower (trade, 'OrderType'); - const feeCost = this.safeFloat (trade, 'Fee'); + const feeCost = this.safeNumber (trade, 'Fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'FeeProductId'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -758,6 +756,11 @@ module.exports = class ndax extends Exchange { }; } } + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const symbol = this.safeSymbol (marketId, market); return { 'info': trade, @@ -872,11 +875,11 @@ module.exports = class ndax extends Exchange { const currencyId = this.safeString (balance, 'ProductId'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'Amount'); - account['used'] = this.safeFloat (balance, 'Hold'); + account['total'] = this.safeString (balance, 'Amount'); + account['used'] = this.safeString (balance, 'Hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseLedgerEntryType (type) { @@ -922,8 +925,8 @@ module.exports = class ndax extends Exchange { const type = this.parseLedgerEntryType (this.safeString (item, 'ReferenceType')); const currencyId = this.safeString (item, 'ProductId'); const code = this.safeCurrencyCode (currencyId, currency); - const credit = this.safeFloat (item, 'CR'); - const debit = this.safeFloat (item, 'DR'); + const credit = this.safeNumber (item, 'CR'); + const debit = this.safeNumber (item, 'DR'); let amount = undefined; let direction = undefined; if (credit > 0) { @@ -935,7 +938,7 @@ module.exports = class ndax extends Exchange { } const timestamp = this.safeInteger (item, 'TimeStamp'); let before = undefined; - const after = this.safeFloat (item, 'Balance'); + const after = this.safeNumber (item, 'Balance'); if (direction === 'out') { before = this.sum (after, amount); } else if (direction === 'in') { @@ -1083,36 +1086,26 @@ module.exports = class ndax extends Exchange { // const id = this.safeString2 (order, 'ReplacementOrderId', 'OrderId'); const timestamp = this.safeInteger (order, 'ReceiveTime'); - let lastTradeTimestamp = undefined; + const lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); const marketId = this.safeString (order, 'Instrument'); const symbol = this.safeSymbol (marketId, market); const side = this.safeStringLower (order, 'Side'); const type = this.safeStringLower (order, 'OrderType'); const clientOrderId = this.safeString2 (order, 'ReplacementClOrdId', 'ClientOrderId'); - let price = this.safeFloat (order, 'Price', 0.0); + let price = this.safeNumber (order, 'Price', 0.0); price = (price > 0.0) ? price : undefined; - const amount = this.safeFloat (order, 'OrigQuantity'); - const filled = this.safeFloat (order, 'QuantityExecuted'); - const cost = this.safeFloat (order, 'GrossValueExecuted'); - let remaining = undefined; - let average = undefined; - if (filled !== undefined) { - if (amount !== undefined) { - remaining = Math.max (0, amount - filled); - } - if (filled > 0) { - lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime'); - average = this.safeFloat (order, 'AvgPrice', 0.0); - average = (average > 0) ? average : undefined; - } - } - let stopPrice = this.safeFloat (order, 'StopPrice', 0.0); + const amount = this.safeNumber (order, 'OrigQuantity'); + const filled = this.safeNumber (order, 'QuantityExecuted'); + const cost = this.safeNumber (order, 'GrossValueExecuted'); + let average = this.safeNumber (order, 'AvgPrice', 0.0); + average = (average > 0) ? average : undefined; + let stopPrice = this.safeNumber (order, 'StopPrice', 0.0); stopPrice = (stopPrice > 0.0) ? stopPrice : undefined; const timeInForce = undefined; const status = this.parseOrderStatus (this.safeString (order, 'OrderState')); const fee = undefined; const trades = undefined; - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -1131,10 +1124,10 @@ module.exports = class ndax extends Exchange { 'amount': amount, 'filled': filled, 'average': average, - 'remaining': remaining, + 'remaining': undefined, 'fee': fee, 'trades': trades, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1932,8 +1925,8 @@ module.exports = class ndax extends Exchange { } const addressTo = address; const status = this.parseTransactionStatusByType (this.safeString (transaction, 'TicketStatus'), type); - const amount = this.safeFloat (transaction, 'Amount'); - const feeCost = this.safeFloat (transaction, 'FeeAmount'); + const amount = this.safeNumber (transaction, 'Amount'); + const feeCost = this.safeNumber (transaction, 'FeeAmount'); let fee = undefined; if (feeCost !== undefined) { fee = { 'currency': code, 'cost': feeCost }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/novadax.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/novadax.js index dfc6569d2..76f763414 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/novadax.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/novadax.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, PermissionDenied, BadRequest, CancelPending, OrderNotFound, InsufficientFunds, RateLimitExceeded, InvalidOrder, AccountSuspended, BadSymbol, OnMaintenance } = require ('./base/errors'); const { TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -197,7 +198,7 @@ module.exports = class novadax extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'minOrderAmount'), + 'min': this.safeNumber (market, 'minOrderAmount'), 'max': undefined, }, 'price': { @@ -205,7 +206,7 @@ module.exports = class novadax extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minOrderValue'), + 'min': this.safeNumber (market, 'minOrderValue'), 'max': undefined, }, }; @@ -247,8 +248,8 @@ module.exports = class novadax extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const open = this.safeFloat (ticker, 'open24h'); - const last = this.safeFloat (ticker, 'lastPrice'); + const open = this.safeNumber (ticker, 'open24h'); + const last = this.safeNumber (ticker, 'lastPrice'); let percentage = undefined; let change = undefined; let average = undefined; @@ -257,18 +258,18 @@ module.exports = class novadax extends Exchange { percentage = change / open * 100; average = this.sum (last, open) / 2; } - const baseVolume = this.safeFloat (ticker, 'baseVolume24h'); - const quoteVolume = this.safeFloat (ticker, 'quoteVolume24h'); + const baseVolume = this.safeNumber (ticker, 'baseVolume24h'); + const quoteVolume = this.safeNumber (ticker, 'quoteVolume24h'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24h'), - 'low': this.safeFloat (ticker, 'low24h'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high24h'), + 'low': this.safeNumber (ticker, 'low24h'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -424,11 +425,13 @@ module.exports = class novadax extends Exchange { const orderId = this.safeString (trade, 'orderId'); const timestamp = this.safeInteger (trade, 'timestamp'); const side = this.safeStringLower (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = this.safeFloat (trade, 'volume'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - cost = amount * price; + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'volume'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); @@ -440,7 +443,7 @@ module.exports = class novadax extends Exchange { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { - 'cost': this.safeFloat (parts, 0), + 'cost': this.safeNumber (parts, 0), 'currency': feeCurrencyCode, }; } @@ -548,11 +551,11 @@ module.exports = class novadax extends Exchange { const volumeField = this.safeString (options, 'volume', 'amount'); // or vol return [ this.safeTimestamp (ohlcv, 'score'), - this.safeFloat (ohlcv, 'openPrice'), - this.safeFloat (ohlcv, 'highPrice'), - this.safeFloat (ohlcv, 'lowPrice'), - this.safeFloat (ohlcv, 'closePrice'), - this.safeFloat (ohlcv, volumeField), + this.safeNumber (ohlcv, 'openPrice'), + this.safeNumber (ohlcv, 'highPrice'), + this.safeNumber (ohlcv, 'lowPrice'), + this.safeNumber (ohlcv, 'closePrice'), + this.safeNumber (ohlcv, volumeField), ]; } @@ -580,12 +583,12 @@ module.exports = class novadax extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'available'); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); + account['total'] = this.safeString (balance, 'available'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'hold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -608,7 +611,7 @@ module.exports = class novadax extends Exchange { if (uppercaseSide === 'SELL') { request['amount'] = this.amountToPrecision (symbol, amount); } else if (uppercaseSide === 'BUY') { - let value = this.safeFloat (params, 'value'); + let value = this.safeNumber (params, 'value'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -838,21 +841,17 @@ module.exports = class novadax extends Exchange { // } // const id = this.safeString (order, 'id'); - const amount = this.safeFloat (order, 'amount'); - const price = this.safeFloat (order, 'price'); - const cost = this.safeFloat (order, 'filledValue'); + const amount = this.safeNumber (order, 'amount'); + const price = this.safeNumber (order, 'price'); + const cost = this.safeNumber (order, 'filledValue'); const type = this.safeStringLower (order, 'type'); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeInteger (order, 'timestamp'); - const average = this.safeFloat (order, 'averagePrice'); - const filled = this.safeFloat (order, 'filledAmount'); - let remaining = undefined; - if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (0, amount - filled); - } + const average = this.safeNumber (order, 'averagePrice'); + const filled = this.safeNumber (order, 'filledAmount'); let fee = undefined; - const feeCost = this.safeFloat (order, 'filledFee'); + const feeCost = this.safeNumber (order, 'filledFee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -861,7 +860,7 @@ module.exports = class novadax extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'info': order, @@ -879,11 +878,11 @@ module.exports = class novadax extends Exchange { 'cost': cost, 'average': average, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } async withdraw (code, amount, address, tag = undefined, params = {}) { @@ -1046,7 +1045,7 @@ module.exports = class novadax extends Exchange { } else if (type === 'COIN_OUT') { type = 'withdraw'; } - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'addressTag'); const txid = this.safeString (transaction, 'txHash'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/oceanex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/oceanex.js index 28cb8e857..6073f75d5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/oceanex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/oceanex.js @@ -147,10 +147,10 @@ module.exports = class oceanex extends Exchange { 'active': true, 'info': market, 'precision': { - 'amount': this.safeValue (market, 'amount_precision'), - 'price': this.safeValue (market, 'price_precision'), - 'base': this.safeValue (market, 'ask_precision'), - 'quote': this.safeValue (market, 'bid_precision'), + 'amount': this.safeInteger (market, 'amount_precision'), + 'price': this.safeInteger (market, 'price_precision'), + 'base': this.safeInteger (market, 'ask_precision'), + 'quote': this.safeInteger (market, 'bid_precision'), }, 'limits': { 'amount': { @@ -162,7 +162,7 @@ module.exports = class oceanex extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeValue (market, 'minimum_trading_amount'), + 'min': this.safeNumber (market, 'minimum_trading_amount'), 'max': undefined, }, }, @@ -256,21 +256,21 @@ module.exports = class oceanex extends Exchange { 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, - 'close': this.safeFloat (ticker, 'last'), - 'last': this.safeFloat (ticker, 'last'), + 'close': this.safeNumber (ticker, 'last'), + 'last': this.safeNumber (ticker, 'last'), 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }; @@ -395,8 +395,8 @@ module.exports = class oceanex extends Exchange { 'type': 'limit', 'takerOrMaker': undefined, 'side': side, - 'price': this.safeFloat (trade, 'price'), - 'amount': this.safeFloat (trade, 'volume'), + 'price': this.safeNumber (trade, 'price'), + 'amount': this.safeNumber (trade, 'volume'), 'cost': undefined, 'fee': undefined, }; @@ -423,8 +423,8 @@ module.exports = class oceanex extends Exchange { result[symbol] = { 'info': group, 'symbol': symbol, - 'maker': this.safeFloat (maker, 'value'), - 'taker': this.safeFloat (taker, 'value'), + 'maker': this.safeNumber (maker, 'value'), + 'taker': this.safeNumber (taker, 'value'), }; } return result; @@ -446,11 +446,11 @@ module.exports = class oceanex extends Exchange { const currencyId = this.safeValue (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -558,12 +558,12 @@ module.exports = class oceanex extends Exchange { // const status = this.parseOrderStatus (this.safeValue (order, 'state')); const marketId = this.safeString2 (order, 'market', 'market_id'); - const symbol = this.safeSymbol (marketId); + const symbol = this.safeSymbol (marketId, market); let timestamp = this.safeTimestamp (order, 'created_on'); if (timestamp === undefined) { timestamp = this.parse8601 (this.safeString (order, 'created_at')); } - return { + return this.safeOrder ({ 'info': order, 'id': this.safeString (order, 'id'), 'clientOrderId': undefined, @@ -575,17 +575,17 @@ module.exports = class oceanex extends Exchange { 'timeInForce': undefined, 'postOnly': undefined, 'side': this.safeValue (order, 'side'), - 'price': this.safeFloat (order, 'price'), + 'price': this.safeNumber (order, 'price'), 'stopPrice': undefined, - 'average': this.safeFloat (order, 'avg_price'), - 'amount': this.safeFloat (order, 'volume'), - 'remaining': this.safeFloat (order, 'remaining_volume'), - 'filled': this.safeFloat (order, 'executed_volume'), + 'average': this.safeNumber (order, 'avg_price'), + 'amount': this.safeNumber (order, 'volume'), + 'remaining': this.safeNumber (order, 'remaining_volume'), + 'filled': this.safeNumber (order, 'executed_volume'), 'status': status, 'cost': undefined, 'trades': undefined, 'fee': undefined, - }; + }); } parseOrderStatus (status) { @@ -678,7 +678,7 @@ module.exports = class oceanex extends Exchange { const feedback = this.id + ' ' + body; this.throwExactlyMatchedException (this.exceptions['codes'], errorCode, feedback); this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback); - throw new ExchangeError (response); + throw new ExchangeError (feedback); } } }; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/okex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/okex.js index b9b09c4e0..02d686c17 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/okex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/okex.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -798,7 +799,7 @@ module.exports = class okex extends Exchange { let option = false; let baseId = this.safeString (market, 'base_currency'); let quoteId = this.safeString (market, 'quote_currency'); - const contractVal = this.safeFloat (market, 'contract_val'); + const contractVal = this.safeNumber (market, 'contract_val'); if (contractVal !== undefined) { if ('option_type' in market) { marketType = 'option'; @@ -824,12 +825,12 @@ module.exports = class okex extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = spot ? (base + '/' + quote) : id; - const lotSize = this.safeFloat2 (market, 'lot_size', 'trade_increment'); + const lotSize = this.safeNumber2 (market, 'lot_size', 'trade_increment'); const precision = { - 'amount': this.safeFloat (market, 'size_increment', lotSize), - 'price': this.safeFloat (market, 'tick_size'), + 'amount': this.safeNumber (market, 'size_increment', lotSize), + 'price': this.safeNumber (market, 'tick_size'), }; - const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size'); + const minAmount = this.safeNumber2 (market, 'min_size', 'base_min_size'); const active = true; const fees = this.safeValue2 (this.fees, marketType, 'trading', {}); return this.extend (fees, { @@ -1004,7 +1005,7 @@ module.exports = class okex extends Exchange { 'price': { 'min': undefined, 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdrawal'), + 'min': this.safeNumber (currency, 'min_withdrawal'), 'max': undefined, }, }, @@ -1079,18 +1080,18 @@ module.exports = class okex extends Exchange { if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open_24h'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open_24h'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_24h'), - 'low': this.safeFloat (ticker, 'low_24h'), - 'bid': this.safeFloat (ticker, 'best_bid'), - 'bidVolume': this.safeFloat (ticker, 'best_bid_size'), - 'ask': this.safeFloat (ticker, 'best_ask'), - 'askVolume': this.safeFloat (ticker, 'best_ask_size'), + 'high': this.safeNumber (ticker, 'high_24h'), + 'low': this.safeNumber (ticker, 'low_24h'), + 'bid': this.safeNumber (ticker, 'best_bid'), + 'bidVolume': this.safeNumber (ticker, 'best_bid_size'), + 'ask': this.safeNumber (ticker, 'best_ask'), + 'askVolume': this.safeNumber (ticker, 'best_ask_size'), 'vwap': undefined, 'open': open, 'close': last, @@ -1099,8 +1100,8 @@ module.exports = class okex extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'base_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'quote_volume_24h'), + 'baseVolume': this.safeNumber (ticker, 'base_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'quote_volume_24h'), 'info': ticker, }; } @@ -1237,9 +1238,12 @@ module.exports = class okex extends Exchange { quote = market['quote']; } const timestamp = this.parse8601 (this.safeString2 (trade, 'timestamp', 'created_at')); - const price = this.safeFloat (trade, 'price'); - let amount = this.safeFloat2 (trade, 'size', 'qty'); - amount = this.safeFloat (trade, 'order_qty', amount); + const priceString = this.safeString (trade, 'price'); + let amountString = this.safeString2 (trade, 'size', 'qty'); + amountString = this.safeString (trade, 'order_qty', amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let takerOrMaker = this.safeString2 (trade, 'exec_type', 'liquidity'); if (takerOrMaker === 'M') { takerOrMaker = 'maker'; @@ -1247,13 +1251,7 @@ module.exports = class okex extends Exchange { takerOrMaker = 'taker'; } const side = this.safeString (trade, 'side'); - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = (side === 'buy') ? base : quote; @@ -1362,22 +1360,22 @@ module.exports = class okex extends Exchange { } return [ timestamp, // timestamp - this.safeFloat (ohlcv, 1), // Open - this.safeFloat (ohlcv, 2), // High - this.safeFloat (ohlcv, 3), // Low - this.safeFloat (ohlcv, 4), // Close - // this.safeFloat (ohlcv, 5), // Quote Volume - // this.safeFloat (ohlcv, 6), // Base Volume - this.safeFloat (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets + this.safeNumber (ohlcv, 1), // Open + this.safeNumber (ohlcv, 2), // High + this.safeNumber (ohlcv, 3), // Low + this.safeNumber (ohlcv, 4), // Close + // this.safeNumber (ohlcv, 5), // Quote Volume + // this.safeNumber (ohlcv, 6), // Base Volume + this.safeNumber (ohlcv, volumeIndex), // Volume, okex will return base volume in the 7th element for future markets ]; } else { return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), // Open - this.safeFloat (ohlcv, 'high'), // High - this.safeFloat (ohlcv, 'low'), // Low - this.safeFloat (ohlcv, 'close'), // Close - this.safeFloat (ohlcv, 'volume'), // Base Volume + this.safeNumber (ohlcv, 'open'), // Open + this.safeNumber (ohlcv, 'high'), // High + this.safeNumber (ohlcv, 'low'), // Low + this.safeNumber (ohlcv, 'close'), // Close + this.safeNumber (ohlcv, 'volume'), // Base Volume ]; } } @@ -1523,9 +1521,9 @@ module.exports = class okex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'hold'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeNumber (balance, 'balance'); + account['used'] = this.safeNumber (balance, 'hold'); + account['free'] = this.safeNumber (balance, 'available'); result[code] = account; } return this.parseBalance (result); @@ -1595,9 +1593,9 @@ module.exports = class okex extends Exchange { const currencyId = parts[1]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (marketBalance, 'balance'); - account['used'] = this.safeFloat (marketBalance, 'hold'); - account['free'] = this.safeFloat (marketBalance, 'available'); + account['total'] = this.safeNumber (marketBalance, 'balance'); + account['used'] = this.safeNumber (marketBalance, 'hold'); + account['free'] = this.safeNumber (marketBalance, 'available'); accounts[code] = account; } else { throw new NotSupported (this.id + ' margin balance response format has changed!'); @@ -1650,29 +1648,29 @@ module.exports = class okex extends Exchange { const code = this.safeCurrencyCode (id); const balance = this.safeValue (info, id, {}); const account = this.account (); - const totalAvailBalance = this.safeFloat (balance, 'total_avail_balance'); + const totalAvailBalance = this.safeNumber (balance, 'total_avail_balance'); if (this.safeString (balance, 'margin_mode') === 'fixed') { const contracts = this.safeValue (balance, 'contracts', []); let free = totalAvailBalance; for (let i = 0; i < contracts.length; i++) { const contract = contracts[i]; - const fixedBalance = this.safeFloat (contract, 'fixed_balance'); - const realizedPnl = this.safeFloat (contract, 'realized_pnl'); - const marginFrozen = this.safeFloat (contract, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (contract, 'margin_for_unfilled'); + const fixedBalance = this.safeNumber (contract, 'fixed_balance'); + const realizedPnl = this.safeNumber (contract, 'realized_pnl'); + const marginFrozen = this.safeNumber (contract, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (contract, 'margin_for_unfilled'); const margin = this.sum (fixedBalance, realizedPnl) - marginFrozen - marginForUnfilled; free = this.sum (free, margin); } account['free'] = free; } else { - const realizedPnl = this.safeFloat (balance, 'realized_pnl'); - const unrealizedPnl = this.safeFloat (balance, 'unrealized_pnl'); - const marginFrozen = this.safeFloat (balance, 'margin_frozen'); - const marginForUnfilled = this.safeFloat (balance, 'margin_for_unfilled'); + const realizedPnl = this.safeNumber (balance, 'realized_pnl'); + const unrealizedPnl = this.safeNumber (balance, 'unrealized_pnl'); + const marginFrozen = this.safeNumber (balance, 'margin_frozen'); + const marginForUnfilled = this.safeNumber (balance, 'margin_for_unfilled'); account['free'] = this.sum (totalAvailBalance, realizedPnl, unrealizedPnl) - marginFrozen - marginForUnfilled; } // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); + account['total'] = this.safeNumber (balance, 'equity'); result[code] = account; } return this.parseBalance (result); @@ -1710,8 +1708,8 @@ module.exports = class okex extends Exchange { } const account = this.account (); // it may be incorrect to use total, free and used for swap accounts - account['total'] = this.safeFloat (balance, 'equity'); - account['free'] = this.safeFloat (balance, 'total_avail_balance'); + account['total'] = this.safeNumber (balance, 'equity'); + account['free'] = this.safeNumber (balance, 'total_avail_balance'); result[symbol] = account; } return this.parseBalance (result); @@ -1915,7 +1913,7 @@ module.exports = class okex extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let notional = this.safeFloat (params, 'notional'); + let notional = this.safeNumber (params, 'notional'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -2125,8 +2123,8 @@ module.exports = class okex extends Exchange { symbol = market['symbol']; } } - let amount = this.safeFloat (order, 'size'); - const filled = this.safeFloat2 (order, 'filled_size', 'filled_qty'); + let amount = this.safeNumber (order, 'size'); + const filled = this.safeNumber2 (order, 'filled_size', 'filled_qty'); let remaining = undefined; if (amount !== undefined) { if (filled !== undefined) { @@ -2137,9 +2135,9 @@ module.exports = class okex extends Exchange { if (type === 'market') { remaining = 0; } - let cost = this.safeFloat2 (order, 'filled_notional', 'funds'); - const price = this.safeFloat (order, 'price'); - let average = this.safeFloat (order, 'price_avg'); + let cost = this.safeNumber2 (order, 'filled_notional', 'funds'); + const price = this.safeNumber (order, 'price'); + let average = this.safeNumber (order, 'price_avg'); if (cost === undefined) { if (filled !== undefined && average !== undefined) { cost = average * filled; @@ -2150,7 +2148,7 @@ module.exports = class okex extends Exchange { } } const status = this.parseOrderStatus (this.safeString (order, 'state')); - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); let fee = undefined; if (feeCost !== undefined) { const feeCurrency = undefined; @@ -2163,7 +2161,7 @@ module.exports = class okex extends Exchange { if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) { clientOrderId = undefined; // fix empty clientOrderId string } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); return { 'info': order, 'id': id, @@ -2407,16 +2405,6 @@ module.exports = class okex extends Exchange { return await this.fetchOrdersByState ('7', symbol, since, limit, params); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - parseDepositAddress (depositAddress, currency = undefined) { // // { @@ -2444,7 +2432,8 @@ module.exports = class okex extends Exchange { async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); - const currency = this.currency (code); + const parts = code.split ('-'); + const currency = this.currency (parts[0]); const request = { 'currency': currency['id'], }; @@ -2457,8 +2446,8 @@ module.exports = class okex extends Exchange { // } // ] // - const addresses = this.parseDepositAddresses (response); - const address = this.safeValue (addresses, code); + const addressesByCode = this.parseDepositAddresses (response); + const address = this.safeValue (addressesByCode, code); if (address === undefined) { throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first'); } @@ -2633,7 +2622,7 @@ module.exports = class okex extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const txid = this.safeString (transaction, 'txid'); const timestamp = this.parse8601 (this.safeString (transaction, 'timestamp')); @@ -2696,19 +2685,19 @@ module.exports = class okex extends Exchange { let feeCurrencyId = undefined; if (receivedCurrencyId === quoteId) { side = this.safeString (otherTrade, 'side'); - amount = this.safeFloat (otherTrade, 'size'); - cost = this.safeFloat (userTrade, 'size'); + amount = this.safeNumber (otherTrade, 'size'); + cost = this.safeNumber (userTrade, 'size'); feeCurrencyId = this.safeString (otherTrade, 'currency'); } else { side = this.safeString (userTrade, 'side'); - amount = this.safeFloat (userTrade, 'size'); - cost = this.safeFloat (otherTrade, 'size'); + amount = this.safeNumber (userTrade, 'size'); + cost = this.safeNumber (otherTrade, 'size'); feeCurrencyId = this.safeString (userTrade, 'currency'); } const id = this.safeString (userTrade, 'trade_id'); - const price = this.safeFloat (userTrade, 'price'); - const feeCostFirst = this.safeFloat (otherTrade, 'fee'); - const feeCostSecond = this.safeFloat (userTrade, 'fee'); + const price = this.safeNumber (userTrade, 'price'); + const feeCostFirst = this.safeNumber (otherTrade, 'fee'); + const feeCostSecond = this.safeNumber (userTrade, 'fee'); const feeCurrencyCodeFirst = this.safeCurrencyCode (this.safeString (otherTrade, 'currency')); const feeCurrencyCodeSecond = this.safeCurrencyCode (this.safeString (userTrade, 'currency')); let fee = undefined; @@ -3140,7 +3129,7 @@ module.exports = class okex extends Exchange { return response; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); let method = undefined; const defaultType = this.safeString2 (this.options, 'fetchPositions', 'defaultType'); @@ -3522,14 +3511,14 @@ module.exports = class okex extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'type')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - const amount = this.safeFloat (item, 'amount'); + const amount = this.safeNumber (item, 'amount'); const timestamp = this.parse8601 (this.safeString (item, 'timestamp')); const fee = { - 'cost': this.safeFloat (item, 'fee'), + 'cost': this.safeNumber (item, 'fee'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; const marketId = this.safeString (item, 'instrument_id'); let symbol = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/paymium.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/paymium.js index 1af0c5355..2d0d8418c 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/paymium.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/paymium.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -96,12 +97,12 @@ module.exports = class paymium extends Exchange { if (free in response) { const account = this.account (); const used = 'locked_' + currencyId; - account['free'] = this.safeFloat (response, free); - account['used'] = this.safeFloat (response, used); + account['free'] = this.safeString (response, free); + account['used'] = this.safeString (response, used); result[code] = account; } } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -120,30 +121,30 @@ module.exports = class paymium extends Exchange { }; const ticker = await this.publicGetDataCurrencyTicker (this.extend (request, params)); const timestamp = this.safeTimestamp (ticker, 'at'); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'price'); + const last = this.safeNumber (ticker, 'price'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'variation'), + 'percentage': this.safeNumber (ticker, 'variation'), 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, @@ -159,15 +160,12 @@ module.exports = class paymium extends Exchange { symbol = market['symbol']; } const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); + const priceString = this.safeString (trade, 'price'); const amountField = 'traded_' + market['base'].toLowerCase (); - const amount = this.safeFloat (trade, amountField); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const amountString = this.safeString (trade, amountField); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); return { 'info': trade, 'id': id, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/phemex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/phemex.js index b1c294ab2..ae494da41 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/phemex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/phemex.js @@ -305,13 +305,13 @@ module.exports = class phemex extends Exchange { }); } - parseSafeFloat (value = undefined) { + parseSafeNumber (value = undefined) { if (value === undefined) { return value; } value = value.replace (',', ''); const parts = value.split (' '); - return this.safeFloat (parts, 0); + return this.safeNumber (parts, 0); } parseSwapMarket (market) { @@ -335,7 +335,9 @@ module.exports = class phemex extends Exchange { // "minPriceEp":5000, // "maxPriceEp":10000000000, // "maxOrderQty":1000000, - // "type":"Perpetual" + // "type":"Perpetual", + // "status":"Listed", + // "tipOrderQty":1000000, // "steps":"50", // "riskLimits":[ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000}, @@ -360,7 +362,7 @@ module.exports = class phemex extends Exchange { // } // const id = this.safeString (market, 'symbol'); - const baseId = this.safeString (market, 'baseCurrency', 'contractUnderlyingAssets'); + const baseId = this.safeString2 (market, 'baseCurrency', 'contractUnderlyingAssets'); const quoteId = this.safeString (market, 'quoteCurrency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); @@ -377,16 +379,16 @@ module.exports = class phemex extends Exchange { } const linear = !inverse; const precision = { - 'amount': this.safeFloat (market, 'lotSize'), - 'price': this.safeFloat (market, 'tickSize'), + 'amount': this.safeNumber (market, 'lotSize'), + 'price': this.safeNumber (market, 'tickSize'), }; const priceScale = this.safeInteger (market, 'priceScale'); const ratioScale = this.safeInteger (market, 'ratioScale'); const valueScale = this.safeInteger (market, 'valueScale'); - const minPriceEp = this.safeFloat (market, 'minPriceEp'); - const maxPriceEp = this.safeFloat (market, 'maxPriceEp'); - const makerFeeRateEr = this.safeFloat (market, 'makerFeeRateEr'); - const takerFeeRateEr = this.safeFloat (market, 'takerFeeRateEr'); + const minPriceEp = this.safeNumber (market, 'minPriceEp'); + const maxPriceEp = this.safeNumber (market, 'maxPriceEp'); + const makerFeeRateEr = this.safeNumber (market, 'makerFeeRateEr'); + const takerFeeRateEr = this.safeNumber (market, 'takerFeeRateEr'); if (makerFeeRateEr !== undefined) { maker = this.fromEn (makerFeeRateEr, ratioScale, 0.00000001); } @@ -404,10 +406,11 @@ module.exports = class phemex extends Exchange { }, 'cost': { 'min': undefined, - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderQty')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderQty')), }, }; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -456,7 +459,9 @@ module.exports = class phemex extends Exchange { // "defaultMakerFee":"0.001", // "defaultMakerFeeEr":100000, // "baseQtyPrecision":6, - // "quoteQtyPrecision":2 + // "quoteQtyPrecision":2, + // "status":"Listed", + // "tipOrderQty":20 // } // const type = this.safeStringLower (market, 'type'); @@ -467,30 +472,31 @@ module.exports = class phemex extends Exchange { const inverse = undefined; const spot = true; const swap = false; - const taker = this.safeFloat (market, 'defaultTakerFee'); - const maker = this.safeFloat (market, 'defaultMakerFee'); + const taker = this.safeNumber (market, 'defaultTakerFee'); + const maker = this.safeNumber (market, 'defaultMakerFee'); const precision = { - 'amount': this.parseSafeFloat (this.safeString (market, 'baseTickSize')), - 'price': this.parseSafeFloat (this.safeString (market, 'quoteTickSize')), + 'amount': this.parseSafeNumber (this.safeString (market, 'baseTickSize')), + 'price': this.parseSafeNumber (this.safeString (market, 'quoteTickSize')), }; const limits = { 'amount': { 'min': precision['amount'], - 'max': this.parseSafeFloat (this.safeString (market, 'maxBaseOrderSize')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxBaseOrderSize')), }, 'price': { 'min': precision['price'], 'max': undefined, }, 'cost': { - 'min': this.parseSafeFloat (this.safeString (market, 'minOrderValue')), - 'max': this.parseSafeFloat (this.safeString (market, 'maxOrderValue')), + 'min': this.parseSafeNumber (this.safeString (market, 'minOrderValue')), + 'max': this.parseSafeNumber (this.safeString (market, 'maxOrderValue')), }, }; const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const active = undefined; + const status = this.safeString (market, 'status'); + const active = status === 'Listed'; return { 'id': id, 'symbol': symbol, @@ -680,8 +686,8 @@ module.exports = class phemex extends Exchange { const name = this.safeString (currency, 'name'); const code = this.safeCurrencyCode (id); const valueScale = this.safeInteger (currency, 'valueScale'); - const minValueEv = this.safeFloat (currency, 'minValueEv'); - const maxValueEv = this.safeFloat (currency, 'maxValueEv'); + const minValueEv = this.safeNumber (currency, 'minValueEv'); + const maxValueEv = this.safeNumber (currency, 'maxValueEv'); let minAmount = undefined; let maxAmount = undefined; let precision = undefined; @@ -731,12 +737,12 @@ module.exports = class phemex extends Exchange { if (market === undefined) { throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument'); } - let amount = this.safeFloat (bidask, amountKey); + let amount = this.safeNumber (bidask, amountKey); if (market['spot']) { amount = this.fromEv (amount, market); } return [ - this.fromEp (this.safeFloat (bidask, priceKey), market), + this.fromEp (this.safeNumber (bidask, priceKey), market), amount, ]; } @@ -870,16 +876,16 @@ module.exports = class phemex extends Exchange { // let baseVolume = undefined; if ((market !== undefined) && market['spot']) { - baseVolume = this.fromEv (this.safeFloat (ohlcv, 7), market); + baseVolume = this.fromEv (this.safeNumber (ohlcv, 7), market); } else { baseVolume = this.safeInteger (ohlcv, 7); } return [ this.safeTimestamp (ohlcv, 0), - this.fromEp (this.safeFloat (ohlcv, 3), market), - this.fromEp (this.safeFloat (ohlcv, 4), market), - this.fromEp (this.safeFloat (ohlcv, 5), market), - this.fromEp (this.safeFloat (ohlcv, 6), market), + this.fromEp (this.safeNumber (ohlcv, 3), market), + this.fromEp (this.safeNumber (ohlcv, 4), market), + this.fromEp (this.safeNumber (ohlcv, 5), market), + this.fromEp (this.safeNumber (ohlcv, 6), market), baseVolume, ]; } @@ -972,11 +978,11 @@ module.exports = class phemex extends Exchange { const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.000001); - const last = this.fromEp (this.safeFloat (ticker, 'lastEp'), market); - const quoteVolume = this.fromEp (this.safeFloat (ticker, 'turnoverEv'), market); - let baseVolume = this.safeFloat (ticker, 'volume'); + const last = this.fromEp (this.safeNumber (ticker, 'lastEp'), market); + const quoteVolume = this.fromEp (this.safeNumber (ticker, 'turnoverEv'), market); + let baseVolume = this.safeNumber (ticker, 'volume'); if (baseVolume === undefined) { - baseVolume = this.fromEv (this.safeFloat (ticker, 'volumeEv')); + baseVolume = this.fromEv (this.safeNumber (ticker, 'volumeEv')); } let vwap = undefined; if ((market !== undefined) && (market['spot'])) { @@ -985,7 +991,7 @@ module.exports = class phemex extends Exchange { let change = undefined; let percentage = undefined; let average = undefined; - const open = this.fromEp (this.safeFloat (ticker, 'openEp'), market); + const open = this.fromEp (this.safeNumber (ticker, 'openEp'), market); if ((open !== undefined) && (last !== undefined)) { change = last - open; if (open > 0) { @@ -997,11 +1003,11 @@ module.exports = class phemex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.fromEp (this.safeFloat (ticker, 'highEp'), market), - 'low': this.fromEp (this.safeFloat (ticker, 'lowEp'), market), - 'bid': this.fromEp (this.safeFloat (ticker, 'bidEp'), market), + 'high': this.fromEp (this.safeNumber (ticker, 'highEp'), market), + 'low': this.fromEp (this.safeNumber (ticker, 'lowEp'), market), + 'bid': this.fromEp (this.safeNumber (ticker, 'bidEp'), market), 'bidVolume': undefined, - 'ask': this.fromEp (this.safeFloat (ticker, 'askEp'), market), + 'ask': this.fromEp (this.safeNumber (ticker, 'askEp'), market), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -1192,8 +1198,8 @@ module.exports = class phemex extends Exchange { id = this.safeString (trade, tradeLength - 4); } side = this.safeStringLower (trade, tradeLength - 3); - price = this.fromEp (this.safeFloat (trade, tradeLength - 2), market); - amount = this.fromEv (this.safeFloat (trade, tradeLength - 1), market); + price = this.fromEp (this.safeNumber (trade, tradeLength - 2), market); + amount = this.fromEv (this.safeNumber (trade, tradeLength - 1), market); if (market['spot']) { if ((price !== undefined) && (amount !== undefined)) { cost = price * amount; @@ -1209,14 +1215,14 @@ module.exports = class phemex extends Exchange { if (execStatus === 'MakerFill') { takerOrMaker = 'maker'; } - price = this.fromEp (this.safeFloat (trade, 'execPriceEp'), market); - amount = this.fromEv (this.safeFloat (trade, 'execBaseQtyEv'), market); - amount = this.safeFloat (trade, 'execQty', amount); - cost = this.fromEv (this.safeFloat2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); - const feeCost = this.fromEv (this.safeFloat (trade, 'execFeeEv'), market); + price = this.fromEp (this.safeNumber (trade, 'execPriceEp'), market); + amount = this.fromEv (this.safeNumber (trade, 'execBaseQtyEv'), market); + amount = this.safeNumber (trade, 'execQty', amount); + cost = this.fromEv (this.safeNumber2 (trade, 'execQuoteQtyEv', 'execValueEv'), market); + const feeCost = this.fromEv (this.safeNumber (trade, 'execFeeEv'), market); if (feeCost !== undefined) { let feeRate = undefined; - let feeRateEr = this.safeFloat (trade, 'feeRateEr'); + let feeRateEr = this.safeNumber (trade, 'feeRateEr'); if (feeRateEr < 0) { feeRateEr = Math.abs (feeRateEr); feeRate = this.fromEr (feeRateEr, market); @@ -1292,9 +1298,9 @@ module.exports = class phemex extends Exchange { const currency = this.safeValue (this.currencies, code, {}); const scale = this.safeInteger (currency, 'valueScale', 8); const account = this.account (); - const balanceEv = this.safeFloat (balance, 'balanceEv'); - const lockedTradingBalanceEv = this.safeFloat (balance, 'lockedTradingBalanceEv'); - const lockedWithdrawEv = this.safeFloat (balance, 'lockedWithdrawEv'); + const balanceEv = this.safeNumber (balance, 'balanceEv'); + const lockedTradingBalanceEv = this.safeNumber (balance, 'lockedTradingBalanceEv'); + const lockedWithdrawEv = this.safeNumber (balance, 'lockedWithdrawEv'); const total = this.fromEn (balanceEv, scale, scale, DECIMAL_PLACES); const lockedTradingBalance = this.fromEn (lockedTradingBalanceEv, scale, scale, DECIMAL_PLACES); const lockedWithdraw = this.fromEn (lockedWithdrawEv, scale, scale, DECIMAL_PLACES); @@ -1388,8 +1394,8 @@ module.exports = class phemex extends Exchange { const code = this.safeCurrencyCode (currencyId); const currency = this.currency (code); const account = this.account (); - const accountBalanceEv = this.safeFloat (balance, 'accountBalanceEv'); - const totalUsedBalanceEv = this.safeFloat (balance, 'totalUsedBalanceEv'); + const accountBalanceEv = this.safeNumber (balance, 'accountBalanceEv'); + const totalUsedBalanceEv = this.safeNumber (balance, 'totalUsedBalanceEv'); const valueScale = this.safeInteger (currency, 'valueScale', 8); account['total'] = this.fromEn (accountBalanceEv, valueScale, valueScale, DECIMAL_PLACES); account['used'] = this.fromEn (totalUsedBalanceEv, valueScale, valueScale, DECIMAL_PLACES); @@ -1621,21 +1627,21 @@ module.exports = class phemex extends Exchange { } const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - let price = this.fromEp (this.safeFloat (order, 'priceEp'), market); + let price = this.fromEp (this.safeNumber (order, 'priceEp'), market); if (price === 0) { price = undefined; } - const amount = this.fromEv (this.safeFloat (order, 'baseQtyEv'), market); - const remaining = this.fromEv (this.safeFloat (order, 'leavesBaseQtyEv'), market); - let filled = this.fromEv (this.safeFloat (order, 'cumBaseQtyEv'), market); - const cost = this.fromEv (this.safeFloat (order, 'quoteQtyEv'), market); - const average = this.fromEp (this.safeFloat (order, 'avgPriceEp'), market); + const amount = this.fromEv (this.safeNumber (order, 'baseQtyEv'), market); + const remaining = this.fromEv (this.safeNumber (order, 'leavesBaseQtyEv'), market); + let filled = this.fromEv (this.safeNumber (order, 'cumBaseQtyEv'), market); + const cost = this.fromEv (this.safeNumber (order, 'quoteQtyEv'), market); + const average = this.fromEp (this.safeNumber (order, 'avgPriceEp'), market); const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'ordType')); const timestamp = this.safeIntegerProduct2 (order, 'actionTimeNs', 'createTimeNs', 0.000001); let fee = undefined; - const feeCost = this.fromEv (this.safeFloat (order, 'cumFeeEv'), market); + const feeCost = this.fromEv (this.safeNumber (order, 'cumFeeEv'), market); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1648,7 +1654,7 @@ module.exports = class phemex extends Exchange { } } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.fromEp (this.safeFloat (order, 'stopPxEp', market)); + const stopPrice = this.fromEp (this.safeNumber (order, 'stopPxEp', market)); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -1721,18 +1727,18 @@ module.exports = class phemex extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const side = this.safeStringLower (order, 'side'); const type = this.parseOrderType (this.safeString (order, 'orderType')); - const price = this.fromEp (this.safeFloat (order, 'priceEp'), market); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); + const price = this.fromEp (this.safeNumber (order, 'priceEp'), market); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); const timestamp = this.safeIntegerProduct (order, 'actionTimeNs', 0.000001); - const cost = this.safeFloat (order, 'cumValue'); + const cost = this.safeNumber (order, 'cumValue'); let lastTradeTimestamp = this.safeIntegerProduct (order, 'transactTimeNs', 0.000001); if (lastTradeTimestamp === 0) { lastTradeTimestamp = undefined; } const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce')); - const stopPrice = this.safeFloat (order, 'stopPx'); + const stopPrice = this.safeNumber (order, 'stopPx'); const postOnly = (timeInForce === 'PO'); return { 'info': order, @@ -1807,7 +1813,7 @@ module.exports = class phemex extends Exchange { } request['qtyType'] = qtyType; if (qtyType === 'ByQuote') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); params = this.omit (params, 'cost'); if (this.options['createOrderByQuoteRequiresPrice']) { if (price !== undefined) { @@ -1827,7 +1833,7 @@ module.exports = class phemex extends Exchange { if (type === 'Limit') { request['priceEp'] = this.toEp (price, market); } - const stopPrice = this.safeFloat2 (params, 'stopPx', 'stopPrice'); + const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice'); if (stopPrice !== undefined) { request['stopPxEp'] = this.toEp (stopPrice, market); } @@ -2335,7 +2341,7 @@ module.exports = class phemex extends Exchange { const code = currency['code']; const timestamp = this.safeInteger2 (transaction, 'createdAt', 'submitedAt'); let type = this.safeStringLower (transaction, 'type'); - const feeCost = this.fromEn (this.safeFloat (transaction, 'feeEv'), currency['valueScale'], currency['precision']); + const feeCost = this.fromEn (this.safeNumber (transaction, 'feeEv'), currency['valueScale'], currency['precision']); let fee = undefined; if (feeCost !== undefined) { type = 'withdrawal'; @@ -2345,7 +2351,7 @@ module.exports = class phemex extends Exchange { }; } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const amount = this.fromEn (this.safeFloat (transaction, 'amountEv'), currency['valueScale'], currency['precision']); + const amount = this.fromEn (this.safeNumber (transaction, 'amountEv'), currency['valueScale'], currency['precision']); return { 'info': transaction, 'id': id, @@ -2367,7 +2373,7 @@ module.exports = class phemex extends Exchange { }; } - async fetchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) { + async fetchPositions (symbols = undefined, params = {}) { await this.loadMarkets (); const code = this.safeString (params, 'code'); const request = {}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/poloniex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/poloniex.js index 30eee15c9..fbb6447ad 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/poloniex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/poloniex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -113,6 +114,7 @@ module.exports = class poloniex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', // starting from Jan 8 2020 'maker': 0.0009, 'taker': 0.0009, @@ -207,24 +209,6 @@ module.exports = class poloniex extends Exchange { }); } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': parseFloat (this.feeToPrecision (symbol, cost)), - }; - } - parseOHLCV (ohlcv, market = undefined) { // // { @@ -240,11 +224,11 @@ module.exports = class poloniex extends Exchange { // return [ this.safeTimestamp (ohlcv, 'date'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'quoteVolume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'quoteVolume'), ]; } @@ -337,11 +321,11 @@ module.exports = class poloniex extends Exchange { const balance = this.safeValue (response, currencyId, {}); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onOrders'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchTradingFees (params = {}) { @@ -359,8 +343,8 @@ module.exports = class poloniex extends Exchange { // return { 'info': fees, - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), 'withdraw': {}, 'deposit': {}, }; @@ -418,8 +402,8 @@ module.exports = class poloniex extends Exchange { let open = undefined; let change = undefined; let average = undefined; - const last = this.safeFloat (ticker, 'last'); - const relativeChange = this.safeFloat (ticker, 'percentChange'); + const last = this.safeNumber (ticker, 'last'); + const relativeChange = this.safeNumber (ticker, 'percentChange'); if (relativeChange !== -1) { open = last / this.sum (1, relativeChange); change = last - open; @@ -429,11 +413,11 @@ module.exports = class poloniex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high24hr'), - 'low': this.safeFloat (ticker, 'low24hr'), - 'bid': this.safeFloat (ticker, 'highestBid'), + 'high': this.safeNumber (ticker, 'high24hr'), + 'low': this.safeNumber (ticker, 'low24hr'), + 'bid': this.safeNumber (ticker, 'highestBid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'lowestAsk'), + 'ask': this.safeNumber (ticker, 'lowestAsk'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -443,8 +427,8 @@ module.exports = class poloniex extends Exchange { 'change': change, 'percentage': relativeChange * 100, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'quoteVolume'), - 'quoteVolume': this.safeFloat (ticker, 'baseVolume'), + 'baseVolume': this.safeNumber (ticker, 'quoteVolume'), + 'quoteVolume': this.safeNumber (ticker, 'baseVolume'), 'info': ticker, }; } @@ -485,7 +469,7 @@ module.exports = class poloniex extends Exchange { const code = this.safeCurrencyCode (id); const active = (currency['delisted'] === 0) && !currency['disabled']; const numericId = this.safeInteger (currency, 'id'); - const fee = this.safeFloat (currency, 'txFee'); + const fee = this.safeNumber (currency, 'txFee'); result[code] = { 'id': id, 'numericId': numericId, @@ -576,13 +560,18 @@ module.exports = class poloniex extends Exchange { } const side = this.safeString (trade, 'type'); let fee = undefined; - const price = this.safeFloat (trade, 'rate'); - const cost = this.safeFloat (trade, 'total'); - const amount = this.safeFloat (trade, 'amount'); + const priceString = this.safeString (trade, 'rate'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'total'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } const feeDisplay = this.safeString (trade, 'feeDisplay'); if (feeDisplay !== undefined) { const parts = feeDisplay.split (' '); - const feeCost = this.safeFloat (parts, 0); + const feeCost = this.safeNumber (parts, 0); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (parts, 1); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -601,7 +590,7 @@ module.exports = class poloniex extends Exchange { } } let takerOrMaker = undefined; - const takerAdjustment = this.safeFloat (trade, 'takerAdjustment'); + const takerAdjustment = this.safeNumber (trade, 'takerAdjustment'); if (takerAdjustment !== undefined) { takerOrMaker = 'taker'; } @@ -847,9 +836,9 @@ module.exports = class poloniex extends Exchange { if (resultingTrades !== undefined) { trades = this.parseTrades (resultingTrades, market); } - const price = this.safeFloat2 (order, 'price', 'rate'); - let remaining = this.safeFloat (order, 'amount'); - let amount = this.safeFloat (order, 'startingAmount'); + const price = this.safeNumber2 (order, 'price', 'rate'); + let remaining = this.safeNumber (order, 'amount'); + let amount = this.safeNumber (order, 'startingAmount'); let filled = undefined; let cost = 0; if (amount !== undefined) { @@ -899,7 +888,7 @@ module.exports = class poloniex extends Exchange { } const id = this.safeString (order, 'orderNumber'); let fee = undefined; - const feeCost = this.safeFloat (order, 'fee'); + const feeCost = this.safeNumber (order, 'fee'); if (feeCost !== undefined) { let feeCurrencyCode = undefined; if (market !== undefined) { @@ -1396,11 +1385,11 @@ module.exports = class poloniex extends Exchange { const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit'; const type = this.safeString (transaction, 'type', defaultType); const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber'); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'paymentID'); // according to https://poloniex.com/fees/ - const feeCost = this.safeFloat (transaction, 'fee', 0); + const feeCost = this.safeNumber (transaction, 'fee', 0); if (type === 'withdrawal') { // poloniex withdrawal amount includes the fee amount = amount - feeCost; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/probit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/probit.js index 522045f2c..2b551ca0a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/probit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/probit.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, BadResponse, BadRequest, InvalidOrder, InsufficientFunds, AuthenticationError, ArgumentsRequired, InvalidAddress, RateLimitExceeded, DDoSProtection, BadSymbol } = require ('./base/errors'); const { TRUNCATE, TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -140,9 +141,11 @@ module.exports = class probit extends Exchange { }, }, 'commonCurrencies': { + 'AUTO': 'Cube', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', 'CBC': 'CryptoBharatCoin', + 'EPS': 'Epanus', // conflict with EPS Ellipsis https://github.com/ccxt/ccxt/issues/8909 'HBC': 'Hybrid Bank Cash', 'UNI': 'UNICORN Token', }, @@ -191,11 +194,11 @@ module.exports = class probit extends Exchange { const costPrecision = this.safeInteger (market, 'cost_precision'); const precision = { 'amount': 1 / Math.pow (10, amountPrecision), - 'price': this.safeFloat (market, 'price_increment'), + 'price': this.safeNumber (market, 'price_increment'), 'cost': 1 / Math.pow (10, costPrecision), }; - const takerFeeRate = this.safeFloat (market, 'taker_fee_rate'); - const makerFeeRate = this.safeFloat (market, 'maker_fee_rate'); + const takerFeeRate = this.safeNumber (market, 'taker_fee_rate'); + const makerFeeRate = this.safeNumber (market, 'maker_fee_rate'); result.push ({ 'id': id, 'info': market, @@ -210,16 +213,16 @@ module.exports = class probit extends Exchange { 'maker': makerFeeRate / 100, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_quantity'), - 'max': this.safeFloat (market, 'max_quantity'), + 'min': this.safeNumber (market, 'min_quantity'), + 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_cost'), - 'max': this.safeFloat (market, 'max_cost'), + 'min': this.safeNumber (market, 'min_cost'), + 'max': this.safeNumber (market, 'max_cost'), }, }, }); @@ -306,7 +309,7 @@ module.exports = class probit extends Exchange { // [ { 'amount': '0.015', 'priority': 1, 'currency_id': 'ETH' }, {} ] for (let j = 0; j < withdrawalFees.length; j++) { const withdrawalFee = withdrawalFees[j]; - const amount = this.safeFloat (withdrawalFee, 'amount'); + const amount = this.safeNumber (withdrawalFee, 'amount'); const priority = this.safeInteger (withdrawalFee, 'priority'); if ((amount !== undefined) && (priority !== undefined)) { fees.push (withdrawalFee); @@ -314,7 +317,7 @@ module.exports = class probit extends Exchange { } const withdrawalFeesByPriority = this.sortBy (fees, 'priority'); const withdrawalFee = this.safeValue (withdrawalFeesByPriority, 0, {}); - const fee = this.safeFloat (withdrawalFee, 'amount'); + const fee = this.safeNumber (withdrawalFee, 'amount'); result[code] = { 'id': id, 'code': code, @@ -337,11 +340,11 @@ module.exports = class probit extends Exchange { 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (platform, 'min_deposit_amount'), + 'min': this.safeNumber (platform, 'min_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (platform, 'min_withdrawal_amount'), + 'min': this.safeNumber (platform, 'min_withdrawal_amount'), 'max': undefined, }, }, @@ -371,11 +374,11 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (balance, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'total'); - account['free'] = this.safeFloat (balance, 'available'); + account['total'] = this.safeString (balance, 'total'); + account['free'] = this.safeString (balance, 'available'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -427,14 +430,6 @@ module.exports = class probit extends Exchange { return this.parseTickers (data, symbols); } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - async fetchTicker (symbol, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -482,8 +477,8 @@ module.exports = class probit extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'time')); const marketId = this.safeString (ticker, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); - const close = this.safeFloat (ticker, 'last'); - const change = this.safeFloat (ticker, 'change'); + const close = this.safeNumber (ticker, 'last'); + const change = this.safeNumber (ticker, 'change'); let percentage = undefined; let open = undefined; if (change !== undefined) { @@ -492,15 +487,15 @@ module.exports = class probit extends Exchange { percentage = (change / open) * 100; } } - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, @@ -642,16 +637,13 @@ module.exports = class probit extends Exchange { marketId = this.safeString (trade, 'market_id', marketId); const symbol = this.safeSymbol (marketId, market, '-'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const orderId = this.safeString (trade, 'order_id'); - const feeCost = this.safeFloat (trade, 'fee_amount'); + const feeCost = this.safeNumber (trade, 'fee_amount'); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_currency_id'); @@ -795,11 +787,11 @@ module.exports = class probit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'start_time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'base_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'base_volume'), ]; } @@ -898,37 +890,24 @@ module.exports = class probit extends Exchange { const marketId = this.safeString (order, 'market_id'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'time')); - let price = this.safeFloat (order, 'limit_price'); - const filled = this.safeFloat (order, 'filled_quantity'); - let remaining = this.safeFloat (order, 'open_quantity'); - const canceledAmount = this.safeFloat (order, 'cancelled_quantity'); + let price = this.safeNumber (order, 'limit_price'); + const filled = this.safeNumber (order, 'filled_quantity'); + let remaining = this.safeNumber (order, 'open_quantity'); + const canceledAmount = this.safeNumber (order, 'cancelled_quantity'); if (canceledAmount !== undefined) { remaining = this.sum (remaining, canceledAmount); } - const amount = this.safeFloat (order, 'quantity', this.sum (filled, remaining)); - let cost = this.safeFloat2 (order, 'filled_cost', 'cost'); + const amount = this.safeNumber (order, 'quantity', this.sum (filled, remaining)); + const cost = this.safeNumber2 (order, 'filled_cost', 'cost'); if (type === 'market') { price = undefined; } - let average = undefined; - if (filled !== undefined) { - if (cost === undefined) { - if (price !== undefined) { - cost = price * filled; - } - } - if (cost !== undefined) { - if (filled > 0) { - average = cost / filled; - } - } - } let clientOrderId = this.safeString (order, 'client_order_id'); if (clientOrderId === '') { clientOrderId = undefined; } const timeInForce = this.safeStringUpper (order, 'time_in_force'); - return { + return this.safeOrder ({ 'id': id, 'info': order, 'clientOrderId': clientOrderId, @@ -945,11 +924,11 @@ module.exports = class probit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'average': average, + 'average': undefined, 'cost': cost, 'fee': undefined, 'trades': undefined, - }; + }); } costToPrecision (symbol, cost) { @@ -979,7 +958,7 @@ module.exports = class probit extends Exchange { } else if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { - let cost = this.safeFloat (params, 'cost'); + let cost = this.safeNumber (params, 'cost'); const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true); if (createMarketBuyOrderRequiresPrice) { if (price !== undefined) { @@ -1104,16 +1083,6 @@ module.exports = class probit extends Exchange { return this.parseDepositAddresses (data); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async withdraw (code, amount, address, tag = undefined, params = {}) { // In order to use this method // you need to allow API withdrawal from the API Settings Page, and @@ -1144,7 +1113,7 @@ module.exports = class probit extends Exchange { parseTransaction (transaction, currency = undefined) { const id = this.safeString (transaction, 'id'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = this.safeString (transaction, 'address'); const tag = this.safeString (transaction, 'destination_tag'); const txid = this.safeString (transaction, 'hash'); @@ -1153,7 +1122,7 @@ module.exports = class probit extends Exchange { const currencyId = this.safeString (transaction, 'currency_id'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); let fee = undefined; if (feeCost !== undefined && feeCost !== 0) { fee = { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/qtrade.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/qtrade.js index aa66545bf..d77b576c4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/qtrade.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/qtrade.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -179,11 +180,11 @@ module.exports = class qtrade extends Exchange { 'quote': quote, 'active': active, 'precision': precision, - 'taker': this.safeFloat (market, 'taker_fee'), - 'maker': this.safeFloat (market, 'maker_fee'), + 'taker': this.safeNumber (market, 'taker_fee'), + 'maker': this.safeNumber (market, 'maker_fee'), 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_buy_value'), + 'min': this.safeNumber (market, 'minimum_buy_value'), 'max': undefined, }, 'price': { @@ -264,12 +265,12 @@ module.exports = class qtrade extends Exchange { 'info': currency, 'type': type, 'name': name, - 'fee': this.safeFloat (config, 'withdraw_fee'), + 'fee': this.safeNumber (config, 'withdraw_fee'), 'precision': this.safeInteger (currency, 'precision'), 'active': active, 'limits': { 'amount': { - 'min': this.safeFloat (currency, 'minimum_order'), + 'min': this.safeNumber (currency, 'minimum_order'), 'max': undefined, }, 'price': { @@ -304,11 +305,11 @@ module.exports = class qtrade extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'time')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'market_volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'market_volume'), ]; } @@ -370,8 +371,8 @@ module.exports = class qtrade extends Exchange { const result = []; for (let j = 0; j < prices.length; j++) { const priceAsString = prices[j]; - const price = this.safeFloat (prices, j); - const amount = this.safeFloat (bidasks, priceAsString); + const price = this.safeNumber (prices, j); + const amount = this.safeNumber (bidasks, priceAsString); result.push ([ price, amount ]); } orderbook[side] = result; @@ -403,12 +404,12 @@ module.exports = class qtrade extends Exchange { const marketId = this.safeString (ticker, 'id_hr'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeIntegerProduct (ticker, 'last_change', 0.001); - const previous = this.safeFloat (ticker, 'day_open'); - const last = this.safeFloat (ticker, 'last'); - const day_change = this.safeFloat (ticker, 'day_change'); + const previous = this.safeNumber (ticker, 'day_open'); + const last = this.safeNumber (ticker, 'last'); + const day_change = this.safeNumber (ticker, 'day_change'); let percentage = undefined; let change = undefined; - let average = this.safeFloat (ticker, 'day_avg_price'); + let average = this.safeNumber (ticker, 'day_avg_price'); if (day_change !== undefined) { percentage = day_change * 100; if (previous !== undefined) { @@ -418,18 +419,18 @@ module.exports = class qtrade extends Exchange { if ((average === undefined) && (last !== undefined) && (previous !== undefined)) { average = this.sum (last, previous) / 2; } - const baseVolume = this.safeFloat (ticker, 'day_volume_market'); - const quoteVolume = this.safeFloat (ticker, 'day_volume_base'); + const baseVolume = this.safeNumber (ticker, 'day_volume_market'); + const quoteVolume = this.safeNumber (ticker, 'day_volume_base'); const vwap = this.vwap (baseVolume, quoteVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'day_high'), - 'low': this.safeFloat (ticker, 'day_low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'day_high'), + 'low': this.safeNumber (ticker, 'day_low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': previous, @@ -637,16 +638,16 @@ module.exports = class qtrade extends Exchange { const side = this.safeString (trade, 'side'); const marketId = this.safeString (trade, 'market_string'); const symbol = this.safeSymbol (marketId, market, '_'); - let cost = this.safeFloat2 (trade, 'base_volume', 'base_amount'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'market_amount', 'amount'); - if ((cost === undefined) && (amount !== undefined) && (price !== undefined)) { - if (price !== undefined) { - cost = price * amount; - } + let cost = this.safeNumber2 (trade, 'base_volume', 'base_amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'market_amount', 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'base_fee'); + const feeCost = this.safeNumber (trade, 'base_fee'); if (feeCost !== undefined) { const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; fee = { @@ -703,7 +704,7 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['free'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'balance'); account['used'] = 0; result[code] = account; } @@ -713,10 +714,10 @@ module.exports = class qtrade extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = (code in result) ? result[code] : this.account (); - account['used'] = this.safeFloat (balance, 'balance'); + account['used'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -845,10 +846,9 @@ module.exports = class qtrade extends Exchange { side = this.safeString (parts, 0); orderType = this.safeString (parts, 1); } - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'market_amount'); - let remaining = this.safeFloat (order, 'market_amount_remaining'); - let filled = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'market_amount'); + const remaining = this.safeNumber (order, 'market_amount_remaining'); const open = this.safeValue (order, 'open', false); const closeReason = this.safeString (order, 'close_reason'); let status = undefined; @@ -860,58 +860,21 @@ module.exports = class qtrade extends Exchange { status = 'closed'; } const marketId = this.safeString (order, 'market_string'); - const symbol = this.safeSymbol (marketId, market, '_'); + market = this.safeMarket (marketId, market, '_'); + const symbol = market['symbol']; const rawTrades = this.safeValue (order, 'trades', []); const parsedTrades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id, 'side': side, 'type': orderType, }); - const numTrades = parsedTrades.length; - let lastTradeTimestamp = undefined; - let feeCost = undefined; - let cost = undefined; - if (numTrades > 0) { - feeCost = 0; - cost = 0; - filled = 0; - remaining = amount; - for (let i = 0; i < parsedTrades.length; i++) { - const trade = parsedTrades[i]; - feeCost = this.sum (trade['fee']['cost'], feeCost); - lastTradeTimestamp = this.safeInteger (trade, 'timestamp'); - cost = this.sum (trade['cost'], cost); - filled = this.sum (trade['amount'], filled); - remaining = Math.max (0, remaining - trade['amount']); - } - } - let fee = undefined; - if (feeCost !== undefined) { - const feeCurrencyCode = (market === undefined) ? undefined : market['quote']; - fee = { - 'currency': feeCurrencyCode, - 'cost': feeCost, - }; - } - if ((amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - let average = undefined; - if (filled !== undefined) { - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': orderType, 'timeInForce': undefined, @@ -919,15 +882,16 @@ module.exports = class qtrade extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, - 'fee': fee, - 'cost': cost, + 'fee': undefined, + 'fees': undefined, + 'cost': undefined, 'trades': parsedTrades, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -1396,7 +1360,7 @@ module.exports = class qtrade extends Exchange { const tagTo = tag; const cancelRequested = this.safeValue (transaction, 'cancel_requested'); const type = (cancelRequested === undefined) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); let status = this.parseTransactionStatus (this.safeString (transaction, 'status')); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/rightbtc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/rightbtc.js index d22048303..c1cc6bc9b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/rightbtc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/rightbtc.js @@ -185,8 +185,8 @@ module.exports = class rightbtc extends Exchange { return result; } - divideSafeFloat (x, key, divisor) { - const value = this.safeFloat (x, key); + divideSafeNumber (x, key, divisor) { + const value = this.safeNumber (x, key); if (value !== undefined) { return value / divisor; } @@ -196,12 +196,12 @@ module.exports = class rightbtc extends Exchange { parseTicker (ticker, market = undefined) { const symbol = market['symbol']; const timestamp = this.safeInteger (ticker, 'date'); - const last = this.divideSafeFloat (ticker, 'last', 1e8); - const high = this.divideSafeFloat (ticker, 'high', 1e8); - const low = this.divideSafeFloat (ticker, 'low', 1e8); - const bid = this.divideSafeFloat (ticker, 'buy', 1e8); - const ask = this.divideSafeFloat (ticker, 'sell', 1e8); - const baseVolume = this.divideSafeFloat (ticker, 'vol24h', 1e8); + const last = this.divideSafeNumber (ticker, 'last', 1e8); + const high = this.divideSafeNumber (ticker, 'high', 1e8); + const low = this.divideSafeNumber (ticker, 'low', 1e8); + const bid = this.divideSafeNumber (ticker, 'buy', 1e8); + const ask = this.divideSafeNumber (ticker, 'sell', 1e8); + const baseVolume = this.divideSafeNumber (ticker, 'vol24h', 1e8); return { 'symbol': symbol, 'timestamp': timestamp, @@ -305,9 +305,9 @@ module.exports = class rightbtc extends Exchange { let id = this.safeString (trade, 'tid'); id = this.safeString (trade, 'trade_id', id); const orderId = this.safeString (trade, 'order_id'); - const price = this.divideSafeFloat (trade, 'price', 1e8); - let amount = this.safeFloat (trade, 'amount'); - amount = this.safeFloat (trade, 'quantity', amount); + const price = this.divideSafeNumber (trade, 'price', 1e8); + let amount = this.safeNumber (trade, 'amount'); + amount = this.safeNumber (trade, 'quantity', amount); if (amount !== undefined) { amount = amount / 1e8; } @@ -404,8 +404,8 @@ module.exports = class rightbtc extends Exchange { const code = this.safeCurrencyCode (currencyId); const account = this.account (); // https://github.com/ccxt/ccxt/issues/3873 - account['free'] = this.divideSafeFloat (balance, 'balance', 1e8); - account['used'] = this.divideSafeFloat (balance, 'frozen', 1e8); + account['free'] = this.divideSafeNumber (balance, 'balance', 1e8); + account['used'] = this.divideSafeNumber (balance, 'frozen', 1e8); result[code] = account; } return this.parseBalance (result); @@ -494,30 +494,18 @@ module.exports = class rightbtc extends Exchange { } else if ('transactTime' in order) { timestamp = order['transactTime']; } - let price = this.safeFloat2 (order, 'limit', 'price'); + let price = this.safeNumber2 (order, 'limit', 'price'); if (price !== undefined) { price = price / 1e8; } - const amount = this.divideSafeFloat (order, 'quantity', 1e8); - let filled = this.divideSafeFloat (order, 'filled_quantity', 1e8); - let remaining = this.divideSafeFloat (order, 'rest', 1e8); - const cost = this.divideSafeFloat (order, 'cost', 1e8); + const amount = this.divideSafeNumber (order, 'quantity', 1e8); + const filled = this.divideSafeNumber (order, 'filled_quantity', 1e8); + const remaining = this.divideSafeNumber (order, 'rest', 1e8); + const cost = this.divideSafeNumber (order, 'cost', 1e8); // lines 483-494 should be generalized into a base class method - if (amount !== undefined) { - if (remaining === undefined) { - if (filled !== undefined) { - remaining = Math.max (0, amount - filled); - } - } - if (filled === undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - } - } - } const type = 'limit'; const side = this.safeStringLower (order, 'side'); - const feeCost = this.divideSafeFloat (order, 'min_fee', 1e8); + const feeCost = this.divideSafeNumber (order, 'min_fee', 1e8); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -525,13 +513,13 @@ module.exports = class rightbtc extends Exchange { feeCurrency = market['quote']; } fee = { - 'rate': this.safeFloat (order, 'fee'), + 'rate': this.safeNumber (order, 'fee'), 'cost': feeCost, 'currency': feeCurrency, }; } const trades = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -553,7 +541,7 @@ module.exports = class rightbtc extends Exchange { 'fee': fee, 'trades': trades, 'average': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ripio.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ripio.js index b3a30607e..8155014d3 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ripio.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/ripio.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { AuthenticationError, ExchangeError, BadSymbol, BadRequest, InvalidOrder, ArgumentsRequired, OrderNotFound, InsufficientFunds, DDoSProtection } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -149,12 +150,12 @@ module.exports = class ripio extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': this.safeFloat (market, 'min_amount'), - 'price': this.safeFloat (market, 'price_tick'), + 'amount': this.safeNumber (market, 'min_amount'), + 'price': this.safeNumber (market, 'price_tick'), }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), + 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { @@ -162,15 +163,15 @@ module.exports = class ripio extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'min_value'), + 'min': this.safeNumber (market, 'min_value'), 'max': undefined, }, }; const active = this.safeValue (market, 'enabled', true); const fees = this.safeValue (market, 'fees', []); const firstFee = this.safeValue (fees, 0, {}); - const maker = this.safeFloat (firstFee, 'maker_fee', 0.0); - const taker = this.safeFloat (firstFee, 'taker_fee', 0.0); + const maker = this.safeNumber (firstFee, 'maker_fee', 0.0); + const taker = this.safeNumber (firstFee, 'taker_fee', 0.0); result.push ({ 'id': id, 'symbol': symbol, @@ -277,18 +278,18 @@ module.exports = class ripio extends Exchange { const timestamp = this.parse8601 (this.safeString (ticker, 'created_at')); const marketId = this.safeString (ticker, 'pair'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'last_price'); - const average = this.safeFloat (ticker, 'avg'); + const last = this.safeNumber (ticker, 'last_price'); + const average = this.safeNumber (ticker, 'avg'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), - 'bidVolume': this.safeFloat (ticker, 'bid_volume'), - 'ask': this.safeFloat (ticker, 'ask'), - 'askVolume': this.safeFloat (ticker, 'ask_volume'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), + 'bidVolume': this.safeNumber (ticker, 'bid_volume'), + 'ask': this.safeNumber (ticker, 'ask'), + 'askVolume': this.safeNumber (ticker, 'ask_volume'), 'vwap': undefined, 'open': undefined, 'close': last, @@ -430,15 +431,14 @@ module.exports = class ripio extends Exchange { if (side !== undefined) { side = side.toLowerCase (); } - const price = this.safeFloat2 (trade, 'price', 'match_price'); - const amount = this.safeFloat2 (trade, 'amount', 'exchanged'); - let cost = undefined; - if ((amount !== undefined) && (price !== undefined)) { - cost = amount * price; - } + const priceString = this.safeString2 (trade, 'price', 'match_price'); + const amountString = this.safeString2 (trade, 'amount', 'exchanged'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'pair'); market = this.safeMarket (marketId, market); - const feeCost = this.safeFloat (trade, takerOrMaker + '_fee'); + const feeCost = this.safeNumber (trade, takerOrMaker + '_fee'); const orderId = this.safeString (trade, takerOrMaker); let fee = undefined; if (feeCost !== undefined) { @@ -512,11 +512,11 @@ module.exports = class ripio extends Exchange { const currencyId = this.safeString (balance, 'symbol'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -775,16 +775,16 @@ module.exports = class ripio extends Exchange { // } // const id = this.safeString (order, 'order_id'); - const amount = this.safeFloat (order, 'amount'); - let cost = this.safeFloat (order, 'notional'); + const amount = this.safeNumber (order, 'amount'); + let cost = this.safeNumber (order, 'notional'); const type = this.safeStringLower (order, 'order_type'); const priceField = (type === 'market') ? 'fill_price' : 'limit_price'; - const price = this.safeFloat (order, priceField); + const price = this.safeNumber (order, priceField); const side = this.safeStringLower (order, 'side'); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.safeTimestamp (order, 'created_at'); let average = this.safeValue (order, 'fill_price'); - let filled = this.safeFloat (order, 'filled'); + let filled = this.safeNumber (order, 'filled'); let remaining = undefined; const fills = this.safeValue (order, 'fills'); let trades = undefined; @@ -819,7 +819,7 @@ module.exports = class ripio extends Exchange { } const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const stopPrice = this.safeFloat (order, 'stop_price'); + const stopPrice = this.safeNumber (order, 'stop_price'); return { 'id': id, 'clientOrderId': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/southxchange.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/southxchange.js index d2bdd8cec..96ca247a0 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/southxchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/southxchange.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -114,14 +115,14 @@ module.exports = class southxchange extends Exchange { const balance = response[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const deposited = this.safeFloat (balance, 'Deposited'); - const unconfirmed = this.safeFloat (balance, 'Unconfirmed'); + const deposited = this.safeString (balance, 'Deposited'); + const unconfirmed = this.safeString (balance, 'Unconfirmed'); const account = this.account (); - account['free'] = this.safeFloat (balance, 'Available'); - account['total'] = this.sum (deposited, unconfirmed); + account['free'] = this.safeString (balance, 'Available'); + account['total'] = Precise.stringAdd (deposited, unconfirmed); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -139,16 +140,16 @@ module.exports = class southxchange extends Exchange { if (market) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'Last'); + const last = this.safeNumber (ticker, 'Last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': undefined, 'low': undefined, - 'bid': this.safeFloat (ticker, 'Bid'), + 'bid': this.safeNumber (ticker, 'Bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'Ask'), + 'ask': this.safeNumber (ticker, 'Ask'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -156,9 +157,9 @@ module.exports = class southxchange extends Exchange { 'last': last, 'previousClose': undefined, 'change': undefined, - 'percentage': this.safeFloat (ticker, 'Variation24Hr'), + 'percentage': this.safeNumber (ticker, 'Variation24Hr'), 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'Volume24Hr'), + 'baseVolume': this.safeNumber (ticker, 'Volume24Hr'), 'quoteVolume': undefined, 'info': ticker, }; @@ -192,14 +193,11 @@ module.exports = class southxchange extends Exchange { parseTrade (trade, market) { const timestamp = this.safeTimestamp (trade, 'At'); - const price = this.safeFloat (trade, 'Price'); - const amount = this.safeFloat (trade, 'Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'Price'); + const amountString = this.safeString (trade, 'Amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const side = this.safeString (trade, 'Type'); let symbol = undefined; if (market !== undefined) { @@ -240,21 +238,13 @@ module.exports = class southxchange extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const timestamp = undefined; - const price = this.safeFloat (order, 'LimitPrice'); - const amount = this.safeFloat (order, 'OriginalAmount'); - const remaining = this.safeFloat (order, 'Amount'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - cost = price * amount; - if (remaining !== undefined) { - filled = amount - remaining; - } - } + const price = this.safeNumber (order, 'LimitPrice'); + const amount = this.safeNumber (order, 'OriginalAmount'); + const remaining = this.safeNumber (order, 'Amount'); const type = 'limit'; const side = this.safeStringLower (order, 'Type'); const id = this.safeString (order, 'Code'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -269,15 +259,14 @@ module.exports = class southxchange extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, - 'filled': filled, + 'cost': undefined, + 'filled': undefined, 'remaining': remaining, 'status': status, 'fee': undefined, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { @@ -410,8 +399,8 @@ module.exports = class southxchange extends Exchange { const type = this.safeString (item, 'Type'); const ledgerEntryType = this.parseLedgerEntryType (type); const code = this.safeCurrencyCode (this.safeString (item, 'CurrencyCode'), currency); - let amount = this.safeFloat (item, 'Amount'); - const after = this.safeFloat (item, 'TotalBalance'); + let amount = this.safeNumber (item, 'Amount'); + const after = this.safeNumber (item, 'TotalBalance'); let before = undefined; if (amount !== undefined) { if (after !== undefined) { @@ -582,7 +571,7 @@ module.exports = class southxchange extends Exchange { // } // const id = this.safeString (transaction, 'MovementId'); - const amount = this.safeFloat (transaction, 'Amount'); + const amount = this.safeNumber (transaction, 'Amount'); const address = this.safeString (transaction, 'Address'); const addressTo = address; const addressFrom = undefined; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/stex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/stex.js index af2e256f3..f4979c48a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/stex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/stex.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, DDoSProtection } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -186,6 +187,7 @@ module.exports = class stex extends Exchange { 'BITSW': 'BITS', 'BHD': 'Bithold', 'BTH': 'Bithereum', + 'MPH': 'Chasyr Token', 'SBTC': 'SBTCT', // SiamBitcoin }, 'options': { @@ -249,7 +251,7 @@ module.exports = class stex extends Exchange { // differentiated fees for each particular method const code = this.safeCurrencyCode (this.safeString (currency, 'code')); const precision = this.safeInteger (currency, 'precision'); - const fee = this.safeFloat (currency, 'withdrawal_fee_const'); // todo: redesign + const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign const active = this.safeValue (currency, 'active', true); result[code] = { 'id': id, @@ -266,11 +268,11 @@ module.exports = class stex extends Exchange { 'price': { 'min': Math.pow (10, -precision), 'max': undefined }, 'cost': { 'min': undefined, 'max': undefined }, 'deposit': { - 'min': this.safeFloat (currency, 'minimum_deposit_amount'), + 'min': this.safeNumber (currency, 'minimum_deposit_amount'), 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minimum_withdrawal_amount'), + 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'), 'max': undefined, }, }, @@ -331,11 +333,11 @@ module.exports = class stex extends Exchange { 'price': this.safeInteger (market, 'market_precision'), }; const active = this.safeValue (market, 'active'); - const minBuyPrice = this.safeFloat (market, 'min_buy_price'); - const minSellPrice = this.safeFloat (market, 'min_sell_price'); + const minBuyPrice = this.safeNumber (market, 'min_buy_price'); + const minSellPrice = this.safeNumber (market, 'min_sell_price'); const minPrice = Math.max (minBuyPrice, minSellPrice); - const buyFee = this.safeFloat (market, 'buy_fee_percent') / 100; - const sellFee = this.safeFloat (market, 'sell_fee_percent') / 100; + const buyFee = this.safeNumber (market, 'buy_fee_percent') / 100; + const sellFee = this.safeNumber (market, 'sell_fee_percent') / 100; const fee = Math.max (buyFee, sellFee); result.push ({ 'id': id, @@ -354,7 +356,7 @@ module.exports = class stex extends Exchange { 'precision': precision, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'min_order_amount'), + 'min': this.safeNumber (market, 'min_order_amount'), 'max': undefined, }, 'price': { 'min': minPrice, 'max': undefined }, @@ -518,8 +520,8 @@ module.exports = class stex extends Exchange { const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString2 (ticker, 'id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let percentage = undefined; if (last !== undefined) { @@ -532,11 +534,11 @@ module.exports = class stex extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -546,20 +548,12 @@ module.exports = class stex extends Exchange { 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volumeQuote'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volumeQuote'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } - parseTickers (tickers, symbols = undefined) { - const result = []; - for (let i = 0; i < tickers.length; i++) { - result.push (this.parseTicker (tickers[i])); - } - return this.filterByArray (result, 'symbol', symbols); - } - async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); const response = await this.publicGetTicker (params); @@ -625,11 +619,11 @@ module.exports = class stex extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -704,12 +698,11 @@ module.exports = class stex extends Exchange { // const id = this.safeString (trade, 'id'); const timestamp = this.safeTimestamp (trade, 'timestamp'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let symbol = undefined; if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; @@ -822,11 +815,11 @@ module.exports = class stex extends Exchange { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id')); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'frozen_balance'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'frozen_balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOrderStatus (status) { @@ -885,9 +878,9 @@ module.exports = class stex extends Exchange { const marketId = this.safeString2 (order, 'currency_pair_id', 'currency_pair_name'); const symbol = this.safeSymbol (marketId, market, '_'); const timestamp = this.safeTimestamp (order, 'timestamp'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'initial_amount'); - const filled = this.safeFloat (order, 'processed_amount'); + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'initial_amount'); + const filled = this.safeNumber (order, 'processed_amount'); let remaining = undefined; let cost = undefined; if (filled !== undefined) { @@ -917,7 +910,7 @@ module.exports = class stex extends Exchange { 'order': id, }); } - const stopPrice = this.safeFloat (order, 'trigger_price'); + const stopPrice = this.safeNumber (order, 'trigger_price'); const result = { 'info': order, 'id': id, @@ -948,7 +941,7 @@ module.exports = class stex extends Exchange { if (numFees > 0) { result['fees'] = []; for (let i = 0; i < fees.length; i++) { - const feeCost = this.safeFloat (fees[i], 'amount'); + const feeCost = this.safeNumber (fees[i], 'amount'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (fees[i], 'currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1532,13 +1525,13 @@ module.exports = class stex extends Exchange { code = currency['code']; } const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal'; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status')); const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts'); const updated = this.safeTimestamp (transaction, 'updated_ts'); const txid = this.safeString (transaction, 'txid'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (transaction, 'fee_currency_id', 'deposit_fee_currency_id'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -1774,8 +1767,8 @@ module.exports = class stex extends Exchange { for (let i = 0; i < data.length; i++) { const id = this.safeString (data[i], 'id'); const code = this.safeCurrencyCode (id); - withdrawFees[code] = this.safeFloat (data[i], 'withdrawal_fee_const'); - depositFees[code] = this.safeFloat (data[i], 'deposit_fee_const'); + withdrawFees[code] = this.safeNumber (data[i], 'withdrawal_fee_const'); + depositFees[code] = this.safeNumber (data[i], 'deposit_fee_const'); } return { 'withdraw': withdrawFees, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/Exchange/test.ticker.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/Exchange/test.ticker.js index 7d91ea0ba..201873531 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/Exchange/test.ticker.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/Exchange/test.ticker.js @@ -74,6 +74,7 @@ module.exports = (exchange, ticker, method, symbol) => { if (![ + 'bybit', 'coinmarketcap', 'xbtce', 'coss', diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/functions/test.number.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/functions/test.number.js index f2e5eedd3..23e9f7926 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/functions/test.number.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/functions/test.number.js @@ -1,6 +1,7 @@ 'use strict' const { numberToString, decimalToPrecision, ROUND, TRUNCATE, DECIMAL_PLACES, TICK_SIZE, PAD_WITH_ZERO, SIGNIFICANT_DIGITS, toWei, fromWei } = require ('../../../../ccxt'); +const Precise = require ('../../../base/Precise') const assert = require ('assert'); // ---------------------------------------------------------------------------- @@ -287,3 +288,58 @@ assert (decimalToPrecision ('1602000000000000000000', TRUNCATE, 3, SIGNIFICANT_D // throws (() => // decimalToPrecision ('0.01', TRUNCATE, -1, TICK_SIZE), // "TICK_SIZE cant be used with negative numPrecisionDigits") + +// ---------------------------------------------------------------------------- + +const w = '-1.123e-6'; +const x = '0.00000002'; +const y = '69696900000'; +const z = '0'; +const a = '1e8'; + +assert (Precise.stringMul (x, y) === '1393.938'); +assert (Precise.stringMul (y, x) === '1393.938'); +assert (Precise.stringAdd (x, y) === '69696900000.00000002'); +assert (Precise.stringAdd (y, x) === '69696900000.00000002'); +assert (Precise.stringSub (x, y) === '-69696899999.99999998'); +assert (Precise.stringSub (y, x) === '69696899999.99999998'); +assert (Precise.stringDiv (x, y, 1) === '0'); +assert (Precise.stringDiv (x, y) === '0'); +assert (Precise.stringDiv (x, y, 19) === '0.0000000000000000002'); +assert (Precise.stringDiv (x, y, 20) === '0.00000000000000000028'); +assert (Precise.stringDiv (x, y, 21) === '0.000000000000000000286'); +assert (Precise.stringDiv (x, y, 22) === '0.0000000000000000002869'); +assert (Precise.stringDiv (y, x) === '3484845000000000000'); + +assert (Precise.stringMul (x, w) === '-0.00000000000002246'); +assert (Precise.stringMul (w, x) === '-0.00000000000002246'); +assert (Precise.stringAdd (x, w) === '-0.000001103'); +assert (Precise.stringAdd (w, x) === '-0.000001103'); +assert (Precise.stringSub (x, w) === '0.000001143'); +assert (Precise.stringSub (w, x) === '-0.000001143'); +assert (Precise.stringDiv (x, w) === '-0.017809439002671415'); +assert (Precise.stringDiv (w, x) === '-56.15'); + +assert (Precise.stringMul (z, w) === '0'); +assert (Precise.stringMul (z, x) === '0'); +assert (Precise.stringMul (z, y) === '0'); +assert (Precise.stringMul (w, z) === '0'); +assert (Precise.stringMul (x, z) === '0'); +assert (Precise.stringMul (y, z) === '0'); +assert (Precise.stringAdd (z, w) === '-0.000001123'); +assert (Precise.stringAdd (z, x) === '0.00000002'); +assert (Precise.stringAdd (z, y) === '69696900000'); +assert (Precise.stringAdd (w, z) === '-0.000001123'); +assert (Precise.stringAdd (x, z) === '0.00000002'); +assert (Precise.stringAdd (y, z) === '69696900000'); + +assert (Precise.stringMul (x, a) === '2'); +assert (Precise.stringMul (a, x) === '2'); +assert (Precise.stringMul (y, a) === '6969690000000000000'); +assert (Precise.stringMul (a, y) === '6969690000000000000'); +assert (Precise.stringDiv (y, a) === '696.969'); +assert (Precise.stringDiv (y, a, -1) === '690'); +assert (Precise.stringDiv (y, a, 0) === '696'); +assert (Precise.stringDiv (y, a, 1) === '696.9'); +assert (Precise.stringDiv (y, a, 2) === '696.96'); +assert (Precise.stringDiv (a, y) === '0.001434784043479695'); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/test.base.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/test.base.js index 0eb7fcffa..6068fa10a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/test.base.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/test/base/test.base.js @@ -167,7 +167,7 @@ describe ('ccxt base code', () => { const exchange = new Exchange ({ 'id': 'mock' }) const propsSeenBefore = index ( - ["isNode", "empty", "keys", "values", "extend", "clone", "index", "ordered", "unique", "keysort", "indexBy", "groupBy", "filterBy", "sortBy", "flatten", "pluck", "omit", "sum", "deepExtend", "uuid", "unCamelCase", "capitalize", "isNumber", "isArray", "isObject", "isString", "isStringCoercible", "isDictionary", "hasProps", "prop", "asFloat", "asInteger", "safeFloat", "safeInteger", "safeValue", "safeString", "decimal", "toFixed", "truncate", "truncateToString", "precisionFromString", "stringToBinary", "stringToBase64", "base64ToBinary", "base64ToString", "binaryToString", "binaryConcat", "urlencode", "rawencode", "urlencodeBase64", "hash", "hmac", "jwt", "time", "setTimeout_safe", "sleep", "TimedOut", "timeout", "throttle", "json", "unjson", "aggregate", "is_node", "index_by", "group_by", "filter_by", "sort_by", "deep_extend", "un_camel_case", "is_number", "is_array", "is_object", "is_string", "is_string_coercible", "is_dictionary", "has_props", "as_float", "as_integer", "safe_float", "safe_integer", "safe_value", "safe_string", "to_fixed", "truncate_to_string", "precision_from_string", "string_to_binary", "string_to_base64", "utf16To_base64", "base64To_binary", "base64To_string", "binary_to_string", "binary_concat", "urlencode_base64", "set_timeout_safe", "Timed_out", "encode", "decode", "userAgents", "headers", "proxy", "origin", "iso8601", "parse8601", "milliseconds", "microseconds", "seconds", "id", "enableRateLimit", "rateLimit", "parseJsonResponse", "substituteCommonCurrencyCodes", "parseBalanceFromOpenOrders", "verbose", "debug", "journal", "userAgent", "twofa", "timeframes", "hasPublicAPI", "hasPrivateAPI", "hasCORS", "hasDeposit", "hasFetchBalance", "hasFetchClosedOrders", "hasFetchCurrencies", "hasFetchMyTrades", "hasFetchOHLCV", "hasFetchOpenOrders", "hasFetchOrder", "hasFetchOrderBook", "hasFetchOrders", "hasFetchTicker", "hasFetchTickers", "hasFetchBidsAsks", "hasFetchTrades", "hasWithdraw", "hasCreateOrder", "hasCancelOrder", "apiKey", "secret", "uid", "login", "password", "requiredCredentials", "exceptions", "balance", "orderbooks", "tickers", "fees", "orders", "trades", "currencies", "last_http_response", "last_json_response", "arrayConcat", "market_id", "market_ids", "array_concat", "implode_params", "extract_params", "fetch_balance", "fetch_free_balance", "fetch_used_balance","fetch_total_balance", "fetch_l2_order_book", "fetch_order_book", "fetch_bids_asks", "fetch_tickers", "fetch_ticker", "fetch_trades", "fetch_order", "fetch_orders", "fetch_open_orders", "fetch_closed_orders", "fetch_order_status", "fetch_markets", "load_markets", "set_markets", "parse_balance", "parse_bid_ask", "parse_bids_asks", "parse_order_book", "parse_trades", "parse_orders", "parse_ohlcv", "parse_ohlcvs", "edit_limit_buy_order", "edit_limit_sell_order", "edit_limit_order", "edit_order", "create_limit_buy_order", "create_limit_sell_order", "create_market_buy_order", "create_market_sell_order", "create_order", "calculate_fee", "common_currency_code", "price_to_precision", "amount_to_precision", "amount_to_string", "fee_to_precision", "cost_to_precision", "constructor", "getMarket", "describe", "defaults", "nonce", "encodeURIComponent", "checkRequiredCredentials", "initRestRateLimiter", "defineRestApi", "fetch", "fetch2", "request", "handleErrors", "defaultErrorHandler", "handleRestErrors", "handleRestResponse", "setMarkets", "loadMarkets", "fetchBidsAsks", "fetchTickers", "fetchOrder", "fetchOrders", "fetchOpenOrders", "fetchClosedOrders", "fetchMyTrades", "fetchCurrencies", "fetchMarkets", "fetchOrderStatus", "account", "commonCurrencyCode", "currency", "market", "marketId", "marketIds", "symbol", "extractParams", "implodeParams", "url", "parseBidAsk", "parseBidsAsks", "fetchL2OrderBook", "parseOrderBook", "parseBalance", "fetchPartialBalance", "fetchFreeBalance", "fetchUsedBalance", "fetchTotalBalance", "filterBySinceLimit", "parseTrades", "parseOrders", "filterOrdersBySymbol", "parseOHLCV", "parseOHLCVs", "editLimitBuyOrder", "editLimitSellOrder", "editLimitOrder", "editOrder", "createLimitBuyOrder", "createLimitSellOrder", "createMarketBuyOrder", "createMarketSellOrder", "costToPrecision", "priceToPrecision", "amountToPrecision", "amountToLots", "feeToPrecision", "calculateFee", "Ymd", "YmdHMS"] + ["isNode", "empty", "keys", "values", "extend", "clone", "index", "ordered", "unique", "keysort", "indexBy", "groupBy", "filterBy", "sortBy", "flatten", "pluck", "omit", "sum", "deepExtend", "uuid", "unCamelCase", "capitalize", "isNumber", "isArray", "isObject", "isString", "isStringCoercible", "isDictionary", "hasProps", "prop", "asFloat", "asInteger", "safeFloat", "safeInteger", "safeValue", "safeString", "decimal", "toFixed", "truncate", "truncateToString", "precisionFromString", "stringToBinary", "stringToBase64", "base64ToBinary", "base64ToString", "binaryToString", "binaryConcat", "urlencode", "rawencode", "urlencodeBase64", "hash", "hmac", "jwt", "time", "setTimeout_safe", "sleep", "TimedOut", "timeout", "throttle", "json", "aggregate", "is_node", "index_by", "group_by", "filter_by", "sort_by", "deep_extend", "un_camel_case", "is_number", "is_array", "is_object", "is_string", "is_string_coercible", "is_dictionary", "has_props", "as_float", "as_integer", "safe_float", "safe_integer", "safe_value", "safe_string", "to_fixed", "truncate_to_string", "precision_from_string", "string_to_binary", "string_to_base64", "utf16To_base64", "base64To_binary", "base64To_string", "binary_to_string", "binary_concat", "urlencode_base64", "set_timeout_safe", "Timed_out", "encode", "decode", "userAgents", "headers", "proxy", "origin", "iso8601", "parse8601", "milliseconds", "microseconds", "seconds", "id", "enableRateLimit", "rateLimit", "parseJsonResponse", "substituteCommonCurrencyCodes", "parseBalanceFromOpenOrders", "verbose", "debug", "journal", "userAgent", "twofa", "timeframes", "hasPublicAPI", "hasPrivateAPI", "hasCORS", "hasDeposit", "hasFetchBalance", "hasFetchClosedOrders", "hasFetchCurrencies", "hasFetchMyTrades", "hasFetchOHLCV", "hasFetchOpenOrders", "hasFetchOrder", "hasFetchOrderBook", "hasFetchOrders", "hasFetchTicker", "hasFetchTickers", "hasFetchBidsAsks", "hasFetchTrades", "hasWithdraw", "hasCreateOrder", "hasCancelOrder", "apiKey", "secret", "uid", "login", "password", "requiredCredentials", "exceptions", "balance", "orderbooks", "tickers", "fees", "orders", "trades", "currencies", "last_http_response", "last_json_response", "arrayConcat", "market_id", "market_ids", "array_concat", "implode_params", "extract_params", "fetch_balance", "fetch_free_balance", "fetch_used_balance","fetch_total_balance", "fetch_l2_order_book", "fetch_order_book", "fetch_bids_asks", "fetch_tickers", "fetch_ticker", "fetch_trades", "fetch_order", "fetch_orders", "fetch_open_orders", "fetch_closed_orders", "fetch_order_status", "fetch_markets", "load_markets", "set_markets", "parse_balance", "parse_bid_ask", "parse_bids_asks", "parse_order_book", "parse_trades", "parse_orders", "parse_ohlcv", "parse_ohlcvs", "edit_limit_buy_order", "edit_limit_sell_order", "edit_limit_order", "edit_order", "create_limit_buy_order", "create_limit_sell_order", "create_market_buy_order", "create_market_sell_order", "create_order", "calculate_fee", "common_currency_code", "price_to_precision", "amount_to_precision", "amount_to_string", "fee_to_precision", "cost_to_precision", "constructor", "getMarket", "describe", "defaults", "nonce", "encodeURIComponent", "checkRequiredCredentials", "initRestRateLimiter", "defineRestApi", "fetch", "fetch2", "request", "handleErrors", "defaultErrorHandler", "handleRestErrors", "handleRestResponse", "setMarkets", "loadMarkets", "fetchBidsAsks", "fetchTickers", "fetchOrder", "fetchOrders", "fetchOpenOrders", "fetchClosedOrders", "fetchMyTrades", "fetchCurrencies", "fetchMarkets", "fetchOrderStatus", "account", "commonCurrencyCode", "currency", "market", "marketId", "marketIds", "symbol", "extractParams", "implodeParams", "url", "parseBidAsk", "parseBidsAsks", "fetchL2OrderBook", "parseOrderBook", "parseBalance", "fetchPartialBalance", "fetchFreeBalance", "fetchUsedBalance", "fetchTotalBalance", "filterBySinceLimit", "parseTrades", "parseOrders", "filterOrdersBySymbol", "parseOHLCV", "parseOHLCVs", "editLimitBuyOrder", "editLimitSellOrder", "editLimitOrder", "editOrder", "createLimitBuyOrder", "createLimitSellOrder", "createMarketBuyOrder", "createMarketSellOrder", "costToPrecision", "priceToPrecision", "amountToPrecision", "amountToLots", "feeToPrecision", "calculateFee", "Ymd", "YmdHMS"] ) const props = index (Object.getOwnPropertyNames (exchange).concat ( diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/therock.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/therock.js index 12217e2b2..88ccb385d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/therock.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/therock.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -171,8 +172,8 @@ module.exports = class therock extends Exchange { const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; - const buy_fee = this.safeFloat (market, 'buy_fee'); - const sell_fee = this.safeFloat (market, 'sell_fee'); + const buy_fee = this.safeNumber (market, 'buy_fee'); + const sell_fee = this.safeNumber (market, 'sell_fee'); let taker = Math.max (buy_fee, sell_fee); taker = taker / 100; const maker = taker; @@ -193,11 +194,11 @@ module.exports = class therock extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minimum_quantity_offer'), + 'min': this.safeNumber (market, 'minimum_quantity_offer'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'minimum_price_offer'), + 'min': this.safeNumber (market, 'minimum_price_offer'), 'max': undefined, }, 'cost': { @@ -221,11 +222,11 @@ module.exports = class therock extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'trading_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'trading_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -244,27 +245,27 @@ module.exports = class therock extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, - 'previousClose': this.safeFloat (ticker, 'close'), // previous day close, if any + 'previousClose': this.safeNumber (ticker, 'close'), // previous day close, if any 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume_traded'), - 'quoteVolume': this.safeFloat (ticker, 'volume'), + 'baseVolume': this.safeNumber (ticker, 'volume_traded'), + 'quoteVolume': this.safeNumber (ticker, 'volume'), 'info': ticker, }; } @@ -339,14 +340,11 @@ module.exports = class therock extends Exchange { const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const side = this.safeString (trade, 'side'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; let feeCost = undefined; const transactions = this.safeValue (trade, 'transactions', []); @@ -356,7 +354,7 @@ module.exports = class therock extends Exchange { if (feeCost === undefined) { feeCost = 0; } - feeCost = this.sum (feeCost, this.safeFloat (feeTransactions[i], 'price')); + feeCost = this.sum (feeCost, this.safeNumber (feeTransactions[i], 'price')); } if (feeCost !== undefined) { fee = { @@ -511,7 +509,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (item, 'price'); + const amount = this.safeNumber (item, 'price'); const timestamp = this.parse8601 (this.safeString (item, 'date')); const status = 'ok'; return { @@ -743,7 +741,7 @@ module.exports = class therock extends Exchange { } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); - const amount = this.safeFloat (transaction, 'price'); + const amount = this.safeNumber (transaction, 'price'); const timestamp = this.parse8601 (this.safeString (transaction, 'date')); const status = 'ok'; // todo parse tags @@ -918,15 +916,15 @@ module.exports = class therock extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'date')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); - const amount = this.safeFloat (order, 'amount'); - const remaining = this.safeFloat (order, 'amount_unfilled'); + const amount = this.safeNumber (order, 'amount'); + const remaining = this.safeNumber (order, 'amount_unfilled'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } - const price = this.safeFloat (order, 'price'); + const price = this.safeNumber (order, 'price'); let trades = this.safeValue (order, 'trades'); let cost = undefined; let average = undefined; @@ -953,7 +951,7 @@ module.exports = class therock extends Exchange { cost = 0; } } - const stopPrice = this.safeFloat (order, 'conditional_price'); + const stopPrice = this.safeNumber (order, 'conditional_price'); return { 'id': id, 'clientOrderId': undefined, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidebit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidebit.js index acf65de25..05efc673a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidebit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidebit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -182,11 +183,11 @@ module.exports = class tidebit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -211,15 +212,15 @@ module.exports = class tidebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), - 'ask': this.safeFloat (ticker, 'sell'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), + 'ask': this.safeNumber (ticker, 'sell'), 'bidVolume': undefined, 'askVolume': undefined, 'vwap': undefined, @@ -230,7 +231,7 @@ module.exports = class tidebit extends Exchange { 'percentage': undefined, 'previousClose': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; @@ -264,9 +265,14 @@ module.exports = class tidebit extends Exchange { parseTrade (trade, market = undefined) { const timestamp = this.parse8601 (this.safeString (trade, 'created_at')); const id = this.safeString (trade, 'id'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'volume'); - const cost = this.safeFloat (trade, 'funds'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber (trade, 'funds'); + if (cost === undefined) { + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + } let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -311,11 +317,11 @@ module.exports = class tidebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), - this.safeFloat (ohlcv, 1), - this.safeFloat (ohlcv, 2), - this.safeFloat (ohlcv, 3), - this.safeFloat (ohlcv, 4), - this.safeFloat (ohlcv, 5), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), ]; } @@ -401,18 +407,12 @@ module.exports = class tidebit extends Exchange { const id = this.safeString (order, 'id'); const type = this.safeString (order, 'ord_type'); const side = this.safeString (order, 'side'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const filled = this.safeFloat (order, 'executed_volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - let cost = undefined; - if (price !== undefined) { - if (filled !== undefined) { - cost = price * filled; - } - } - const average = this.safeFloat (order, 'avg_price'); - return { + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const filled = this.safeNumber (order, 'executed_volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const average = this.safeNumber (order, 'avg_price'); + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -429,12 +429,12 @@ module.exports = class tidebit extends Exchange { 'amount': amount, 'filled': filled, 'remaining': remaining, - 'cost': cost, + 'cost': undefined, 'trades': undefined, 'fee': undefined, 'info': order, 'average': average, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidex.js index 0988a4ad1..65c0e6d9e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/tidex.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class tidex extends Exchange { describe () { @@ -83,6 +84,7 @@ module.exports = class tidex extends Exchange { }, 'fees': { 'trading': { + 'feeSide': 'get', 'tierBased': false, 'percentage': true, 'taker': 0.1 / 100, @@ -127,19 +129,48 @@ module.exports = class tidex extends Exchange { async fetchCurrencies (params = {}) { const response = await this.webGetCurrency (params); + // + // [ + // { + // "id":2, + // "symbol":"BTC", + // "type":2, + // "name":"Bitcoin", + // "amountPoint":8, + // "depositEnable":true, + // "depositMinAmount":0.0005, + // "withdrawEnable":true, + // "withdrawFee":0.0004, + // "withdrawMinAmount":0.0005, + // "settings":{ + // "Blockchain":"https://blockchair.com/bitcoin/", + // "TxUrl":"https://blockchair.com/bitcoin/transaction/{0}", + // "AddrUrl":"https://blockchair.com/bitcoin/address/{0}", + // "ConfirmationCount":3, + // "NeedMemo":false + // }, + // "visible":true, + // "isDelisted":false + // } + // ] + // const result = {}; for (let i = 0; i < response.length; i++) { const currency = response[i]; const id = this.safeString (currency, 'symbol'); - const precision = currency['amountPoint']; + const precision = this.safeInteger (currency, 'amountPoint'); const code = this.safeCurrencyCode (id); - let active = currency['visible'] === true; - const canWithdraw = currency['withdrawEnable'] === true; - const canDeposit = currency['depositEnable'] === true; + const visible = this.safeValue (currency, 'visible'); + let active = visible === true; + const withdrawEnable = this.safeValue (currency, 'withdrawEnable'); + const depositEnable = this.safeValue (currency, 'depositEnable'); + const canWithdraw = withdrawEnable === true; + const canDeposit = depositEnable === true; if (!canWithdraw || !canDeposit) { active = false; } const name = this.safeString (currency, 'name'); + const fee = this.safeNumber (currency, 'withdrawFee'); result[code] = { 'id': id, 'code': code, @@ -149,7 +180,7 @@ module.exports = class tidex extends Exchange { 'funding': { 'withdraw': { 'active': canWithdraw, - 'fee': currency['withdrawFee'], + 'fee': fee, }, 'deposit': { 'active': canDeposit, @@ -170,11 +201,11 @@ module.exports = class tidex extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'withdrawMinAmount'), + 'min': this.safeNumber (currency, 'withdrawMinAmount'), 'max': undefined, }, 'deposit': { - 'min': this.safeFloat (currency, 'depositMinAmount'), + 'min': this.safeNumber (currency, 'depositMinAmount'), 'max': undefined, }, }, @@ -184,26 +215,25 @@ module.exports = class tidex extends Exchange { return result; } - calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { - const market = this.markets[symbol]; - let key = 'quote'; - const rate = market[takerOrMaker]; - let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); - if (side === 'sell') { - cost *= price; - } else { - key = 'base'; - } - return { - 'type': takerOrMaker, - 'currency': market[key], - 'rate': rate, - 'cost': cost, - }; - } - async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615861869, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":3.0, + // "min_amount":0.001, + // "max_amount":1000000.0, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.1, + // }, + // }, + // } + // const markets = response['pairs']; const keys = Object.keys (markets); const result = []; @@ -220,19 +250,20 @@ module.exports = class tidex extends Exchange { }; const limits = { 'amount': { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }, 'price': { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }, 'cost': { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }, }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -241,7 +272,7 @@ module.exports = class tidex extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -262,11 +293,11 @@ module.exports = class tidex extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (funds, currencyId, {}); const account = this.account (); - account['free'] = this.safeFloat (balance, 'value'); - account['used'] = this.safeFloat (balance, 'inOrders'); + account['free'] = this.safeString (balance, 'value'); + account['used'] = this.safeString (balance, 'inOrders'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -338,16 +369,16 @@ module.exports = class tidex extends Exchange { timestamp = undefined; } } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -356,9 +387,9 @@ module.exports = class tidex extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -406,16 +437,19 @@ module.exports = class tidex extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const orderId = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const type = 'limit'; // all trades are still limit trades let takerOrMaker = undefined; let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -434,12 +468,6 @@ module.exports = class tidex extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': orderId, @@ -495,17 +523,18 @@ module.exports = class tidex extends Exchange { let status = 'open'; let filled = 0.0; let remaining = amount; - if ('return' in response) { - id = this.safeString (response['return'], 'order_id'); + const returnResult = this.safeValue (response, 'return'); + if (returnResult !== undefined) { + id = this.safeString (returnResult, 'order_id'); if (id === '0') { - id = this.safeString (response['return'], 'init_order_id'); + id = this.safeString (returnResult, 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (returnResult, 'received', filled); + remaining = this.safeNumber (returnResult, 'remains', amount); } const timestamp = this.milliseconds (); - return { + return this.safeOrder ({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), @@ -515,7 +544,7 @@ module.exports = class tidex extends Exchange { 'type': type, 'side': side, 'price': price, - 'cost': price * filled, + 'cost': undefined, 'amount': amount, 'remaining': remaining, 'filled': filled, @@ -525,7 +554,7 @@ module.exports = class tidex extends Exchange { 'clientOrderId': undefined, 'average': undefined, 'trades': undefined, - }; + }); } async cancelOrder (id, symbol = undefined, params = {}) { @@ -554,23 +583,15 @@ module.exports = class tidex extends Exchange { const symbol = this.safeSymbol (marketId, market); let remaining = undefined; let amount = undefined; - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; + const price = this.safeNumber (order, 'rate'); if ('start_amount' in order) { - amount = this.safeFloat (order, 'start_amount'); - remaining = this.safeFloat (order, 'amount'); + amount = this.safeNumber (order, 'start_amount'); + remaining = this.safeNumber (order, 'amount'); } else { - remaining = this.safeFloat (order, 'amount'); - } - if (amount !== undefined) { - if (remaining !== undefined) { - filled = amount - remaining; - cost = price * filled; - } + remaining = this.safeNumber (order, 'amount'); } const fee = undefined; - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -584,15 +605,15 @@ module.exports = class tidex extends Exchange { 'side': this.safeString (order, 'type'), 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/timex.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/timex.js index 4c71ac4ff..227f97553 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/timex.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/timex.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, PermissionDenied, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, RateLimitExceeded, NotSupported, BadRequest, AuthenticationError } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class timex extends Exchange { describe () { @@ -450,11 +451,11 @@ module.exports = class timex extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['total'] = this.safeFloat (balance, 'totalBalance'); - account['used'] = this.safeFloat (balance, 'lockedBalance'); + account['total'] = this.safeString (balance, 'totalBalance'); + account['used'] = this.safeString (balance, 'lockedBalance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -815,7 +816,7 @@ module.exports = class timex extends Exchange { const result = this.safeValue (response, 0, {}); return { 'info': response, - 'maker': this.safeFloat (result, 'fee'), + 'maker': this.safeNumber (result, 'fee'), 'taker': undefined, }; } @@ -852,18 +853,18 @@ module.exports = class timex extends Exchange { 'amount': this.precisionFromString (this.safeString (market, 'quantityIncrement')), 'price': this.precisionFromString (this.safeString (market, 'tickSize')), }; - const amountIncrement = this.safeFloat (market, 'quantityIncrement'); - const minBase = this.safeFloat (market, 'baseMinSize'); + const amountIncrement = this.safeNumber (market, 'quantityIncrement'); + const minBase = this.safeNumber (market, 'baseMinSize'); const minAmount = Math.max (amountIncrement, minBase); - const priceIncrement = this.safeFloat (market, 'tickSize'); - const minCost = this.safeFloat (market, 'quoteMinSize'); + const priceIncrement = this.safeNumber (market, 'tickSize'); + const minCost = this.safeNumber (market, 'quoteMinSize'); const limits = { 'amount': { 'min': minAmount, 'max': undefined }, 'price': { 'min': priceIncrement, 'max': undefined }, 'cost': { 'min': Math.max (minCost, minAmount * priceIncrement), 'max': undefined }, }; - const taker = this.safeFloat (market, 'takerFee'); - const maker = this.safeFloat (market, 'makerFee'); + const taker = this.safeNumber (market, 'takerFee'); + const maker = this.safeNumber (market, 'makerFee'); return { 'id': id, 'symbol': symbol, @@ -924,7 +925,7 @@ module.exports = class timex extends Exchange { const name = this.safeString (currency, 'name'); const precision = this.safeInteger (currency, 'decimals'); const active = this.safeValue (currency, 'active'); - // const fee = this.safeFloat (currency, 'withdrawalFee'); + // const fee = this.safeNumber (currency, 'withdrawalFee'); const feeString = this.safeString (currency, 'withdrawalFee'); const tradeDecimals = this.safeInteger (currency, 'tradeDecimals'); let fee = undefined; @@ -961,14 +962,6 @@ module.exports = class timex extends Exchange { }; } - parseTickers (rawTickers, symbols = undefined) { - const tickers = []; - for (let i = 0; i < rawTickers.length; i++) { - tickers.push (this.parseTicker (rawTickers[i])); - } - return this.filterByArray (tickers, 'symbol', symbols); - } - parseTicker (ticker, market = undefined) { // // { @@ -988,8 +981,8 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (ticker, 'market'); const symbol = this.safeSymbol (marketId, market, '/'); const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp')); - const last = this.safeFloat (ticker, 'last'); - const open = this.safeFloat (ticker, 'open'); + const last = this.safeNumber (ticker, 'last'); + const open = this.safeNumber (ticker, 'open'); let change = undefined; let average = undefined; if (last !== undefined && open !== undefined) { @@ -1005,11 +998,11 @@ module.exports = class timex extends Exchange { 'info': ticker, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -1019,8 +1012,8 @@ module.exports = class timex extends Exchange { 'change': change, 'percentage': percentage, 'average': average, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'volumeQuote'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'volumeQuote'), }; } @@ -1039,23 +1032,27 @@ module.exports = class timex extends Exchange { // fetchMyTrades, fetchOrder (private) // // { - // "fee": "0.3", - // "id": 100, - // "makerOrTaker": "MAKER", - // "makerOrderId": "string", - // "price": "0.017", - // "quantity": "0.3", + // "id": "7613414", + // "makerOrderId": "0x8420af060722f560098f786a2894d4358079b6ea5d14b395969ed77bc87a623a", + // "takerOrderId": "0x1235ef158a361815b54c9988b6241c85aedcbc1fe81caf8df8587d5ab0373d1a", + // "symbol": "LTCUSDT", // "side": "BUY", - // "symbol": "TIMEETH", - // "takerOrderId": "string", - // "timestamp": "2019-12-08T04:54:11.171Z" - // } + // "quantity": "0.2", + // "fee": "0.22685", + // "feeToken": "USDT", + // "price": "226.85", + // "makerOrTaker": "TAKER", + // "timestamp": "2021-04-09T15:39:45.608" + // } // const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (trade, 'timestamp')); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'quantity'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const id = this.safeString (trade, 'id'); const side = this.safeStringLower2 (trade, 'direction', 'side'); const takerOrMaker = this.safeStringLower (trade, 'makerOrTaker'); @@ -1064,18 +1061,14 @@ module.exports = class timex extends Exchange { orderId = this.safeString (trade, takerOrMaker + 'OrderId'); } let fee = undefined; - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); + const feeCurrency = this.safeCurrencyCode (this.safeString (trade, 'feeToken')); if (feeCost !== undefined) { - const feeCurrency = (market === undefined) ? undefined : market['quote']; fee = { 'cost': feeCost, 'currency': feeCurrency, }; } - let cost = undefined; - if ((price !== undefined) && (amount !== undefined)) { - cost = this.costToPrecision (symbol, amount * price); - } return { 'info': trade, 'id': id, @@ -1107,11 +1100,11 @@ module.exports = class timex extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'timestamp')), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -1142,14 +1135,12 @@ module.exports = class timex extends Exchange { const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (order, 'createdAt')); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'quantity'); - const filled = this.safeFloat (order, 'filledQuantity'); - const canceledQuantity = this.safeFloat (order, 'cancelledQuantity'); - let remaining = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'filledQuantity'); + const canceledQuantity = this.safeNumber (order, 'cancelledQuantity'); let status = undefined; if ((amount !== undefined) && (filled !== undefined)) { - remaining = Math.max (amount - filled, 0.0); if (filled >= amount) { status = 'closed'; } else if ((canceledQuantity !== undefined) && (canceledQuantity > 0)) { @@ -1158,30 +1149,19 @@ module.exports = class timex extends Exchange { status = 'open'; } } - const cost = parseFloat (this.costToPrecision (symbol, price * filled)); - const fee = undefined; - let lastTradeTimestamp = undefined; - let trades = undefined; - const rawTrades = this.safeValue (order, 'trades'); - if (rawTrades !== undefined) { - trades = this.parseTrades (rawTrades, market, undefined, undefined, { - 'order': id, - }); - } - if (trades !== undefined) { - const numTrades = trades.length; - if (numTrades > 0) { - lastTradeTimestamp = trades[numTrades - 1]['timestamp']; - } - } + const rawTrades = this.safeValue (order, 'trades', []); + const trades = this.parseTrades (rawTrades, market, undefined, undefined, { + 'order': id, + 'type': type, + }); const clientOrderId = this.safeString (order, 'clientOrderId'); - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': clientOrderId, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'lastTradeTimestamp': lastTradeTimestamp, + 'lastTradeTimestamp': undefined, 'symbol': symbol, 'type': type, 'timeInForce': undefined, @@ -1190,14 +1170,14 @@ module.exports = class timex extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, - 'fee': fee, + 'fee': undefined, 'trades': trades, - }; + }); } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/upbit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/upbit.js index 829aa6586..890c30126 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/upbit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/upbit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, PermissionDenied, AddressPending } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -229,9 +230,9 @@ module.exports = class upbit extends Exchange { } else if ((locked !== undefined) && locked) { active = false; } - const maxOnetimeWithdrawal = this.safeFloat (withdrawLimits, 'onetime'); - const maxDailyWithdrawal = this.safeFloat (withdrawLimits, 'daily', maxOnetimeWithdrawal); - const remainingDailyWithdrawal = this.safeFloat (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); + const maxOnetimeWithdrawal = this.safeNumber (withdrawLimits, 'onetime'); + const maxDailyWithdrawal = this.safeNumber (withdrawLimits, 'daily', maxOnetimeWithdrawal); + const remainingDailyWithdrawal = this.safeNumber (withdrawLimits, 'remaining_daily', maxDailyWithdrawal); let maxWithdrawLimit = undefined; if (remainingDailyWithdrawal > 0) { maxWithdrawLimit = remainingDailyWithdrawal; @@ -247,11 +248,11 @@ module.exports = class upbit extends Exchange { 'code': code, 'name': code, 'active': active, - 'fee': this.safeFloat (currencyInfo, 'withdraw_fee'), + 'fee': this.safeNumber (currencyInfo, 'withdraw_fee'), 'precision': precision, 'limits': { 'withdraw': { - 'min': this.safeFloat (withdrawLimits, 'minimum'), + 'min': this.safeNumber (withdrawLimits, 'minimum'), 'max': maxWithdrawLimit, }, }, @@ -314,8 +315,8 @@ module.exports = class upbit extends Exchange { }; const state = this.safeString (marketInfo, 'state'); const active = (state === 'active'); - const bidFee = this.safeFloat (response, 'bid_fee'); - const askFee = this.safeFloat (response, 'ask_fee'); + const bidFee = this.safeNumber (response, 'bid_fee'); + const askFee = this.safeNumber (response, 'ask_fee'); const fee = Math.max (bidFee, askFee); return { 'info': response, @@ -331,7 +332,7 @@ module.exports = class upbit extends Exchange { 'taker': fee, 'limits': { 'amount': { - 'min': this.safeFloat (ask, 'min_total'), + 'min': this.safeNumber (ask, 'min_total'), 'max': undefined, }, 'price': { @@ -339,8 +340,8 @@ module.exports = class upbit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (bid, 'min_total'), - 'max': this.safeFloat (marketInfo, 'max_total'), + 'min': this.safeNumber (bid, 'min_total'), + 'max': this.safeNumber (marketInfo, 'max_total'), }, }, }; @@ -379,8 +380,8 @@ module.exports = class upbit extends Exchange { 'price': 8, }; const active = true; - const makerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); - const takerFee = this.safeFloat (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); + const makerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']); + const takerFee = this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']); result.push ({ 'id': id, 'symbol': symbol, @@ -433,11 +434,11 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'balance'); - account['used'] = this.safeFloat (balance, 'locked'); + account['free'] = this.safeString (balance, 'balance'); + account['used'] = this.safeString (balance, 'locked'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) { @@ -540,30 +541,30 @@ module.exports = class upbit extends Exchange { const timestamp = this.safeInteger (ticker, 'trade_timestamp'); const marketId = this.safeString2 (ticker, 'market', 'code'); const symbol = this.safeSymbol (marketId, market, '-'); - const previous = this.safeFloat (ticker, 'prev_closing_price'); - const last = this.safeFloat (ticker, 'trade_price'); - const change = this.safeFloat (ticker, 'signed_change_price'); - const percentage = this.safeFloat (ticker, 'signed_change_rate'); + const previous = this.safeNumber (ticker, 'prev_closing_price'); + const last = this.safeNumber (ticker, 'trade_price'); + const change = this.safeNumber (ticker, 'signed_change_price'); + const percentage = this.safeNumber (ticker, 'signed_change_rate'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high_price'), - 'low': this.safeFloat (ticker, 'low_price'), + 'high': this.safeNumber (ticker, 'high_price'), + 'low': this.safeNumber (ticker, 'low_price'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'opening_price'), + 'open': this.safeNumber (ticker, 'opening_price'), 'close': last, 'last': last, 'previousClose': previous, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'acc_trade_volume_24h'), - 'quoteVolume': this.safeFloat (ticker, 'acc_trade_price_24h'), + 'baseVolume': this.safeNumber (ticker, 'acc_trade_volume_24h'), + 'quoteVolume': this.safeNumber (ticker, 'acc_trade_price_24h'), 'info': ticker, }; } @@ -670,15 +671,13 @@ module.exports = class upbit extends Exchange { } else if (askOrBid === 'bid') { side = 'buy'; } - let cost = this.safeFloat (trade, 'funds'); - const price = this.safeFloat2 (trade, 'trade_price', 'price'); - const amount = this.safeFloat2 (trade, 'trade_volume', 'volume'); + let cost = this.safeNumber (trade, 'funds'); + const priceString = this.safeString2 (trade, 'trade_price', 'price'); + const amountString = this.safeString2 (trade, 'trade_volume', 'volume'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); if (cost === undefined) { - if (amount !== undefined) { - if (price !== undefined) { - cost = price * amount; - } - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const marketId = this.safeString2 (trade, 'market', 'code'); market = this.safeMarket (marketId, market); @@ -773,11 +772,11 @@ module.exports = class upbit extends Exchange { // return [ this.parse8601 (this.safeString (ohlcv, 'candle_date_time_utc')), - this.safeFloat (ohlcv, 'opening_price'), - this.safeFloat (ohlcv, 'high_price'), - this.safeFloat (ohlcv, 'low_price'), - this.safeFloat (ohlcv, 'trade_price'), - this.safeFloat (ohlcv, 'candle_acc_trade_volume'), // base volume + this.safeNumber (ohlcv, 'opening_price'), + this.safeNumber (ohlcv, 'high_price'), + this.safeNumber (ohlcv, 'low_price'), + this.safeNumber (ohlcv, 'trade_price'), + this.safeNumber (ohlcv, 'candle_acc_trade_volume'), // base volume ]; } @@ -1046,7 +1045,7 @@ module.exports = class upbit extends Exchange { // } // const id = this.safeString (transaction, 'uuid'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const address = undefined; // not present in the data structure received from the exchange const tag = undefined; // not present in the data structure received from the exchange const txid = this.safeString (transaction, 'txid'); @@ -1059,7 +1058,7 @@ module.exports = class upbit extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); const status = this.parseTransactionStatus (this.safeString (transaction, 'state')); - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); return { 'info': transaction, 'id': id, @@ -1144,10 +1143,10 @@ module.exports = class upbit extends Exchange { const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const status = this.parseOrderStatus (this.safeString (order, 'state')); let lastTradeTimestamp = undefined; - let price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'volume'); - const remaining = this.safeFloat (order, 'remaining_volume'); - const filled = this.safeFloat (order, 'executed_volume'); + let price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'volume'); + const remaining = this.safeNumber (order, 'remaining_volume'); + const filled = this.safeNumber (order, 'executed_volume'); let cost = undefined; if (type === 'price') { type = 'market'; @@ -1156,7 +1155,7 @@ module.exports = class upbit extends Exchange { } let average = undefined; let fee = undefined; - let feeCost = this.safeFloat (order, 'paid_fee'); + let feeCost = this.safeNumber (order, 'paid_fee'); const marketId = this.safeString (order, 'market'); market = this.safeMarket (marketId, market); let trades = this.safeValue (order, 'trades', []); @@ -1179,7 +1178,7 @@ module.exports = class upbit extends Exchange { cost = this.sum (cost, trade['cost']); if (getFeesFromTrades) { const tradeFee = this.safeValue (trades[i], 'fee', {}); - const tradeFeeCost = this.safeFloat (tradeFee, 'cost'); + const tradeFeeCost = this.safeNumber (tradeFee, 'cost'); if (tradeFeeCost !== undefined) { feeCost = this.sum (feeCost, tradeFeeCost); } @@ -1321,16 +1320,6 @@ module.exports = class upbit extends Exchange { return this.parseOrder (response); } - parseDepositAddresses (addresses) { - const result = {}; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - const code = address['currency']; - result[code] = address; - } - return result; - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetDepositsCoinAddresses (params); diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vaultoro.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vaultoro.js deleted file mode 100644 index abc1ba387..000000000 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vaultoro.js +++ /dev/null @@ -1,203 +0,0 @@ -'use strict'; - -// --------------------------------------------------------------------------- - -const Exchange = require ('./base/Exchange'); - -// --------------------------------------------------------------------------- - -module.exports = class vaultoro extends Exchange { - describe () { - return this.deepExtend (super.describe (), { - 'id': 'vaultoro', - 'name': 'Vaultoro', - 'countries': [ 'CH' ], - 'rateLimit': 1000, - 'version': '1', - 'has': { - 'CORS': true, - 'fetchMarkets': true, - 'fetchOrderBook': true, - 'fetchBalance': true, - 'createOrder': true, - 'cancelOrder': true, - 'fetchTrades': true, - 'fetchTicker': false, - }, - 'urls': { - 'logo': 'https://user-images.githubusercontent.com/1294454/27766880-f205e870-5ee9-11e7-8fe2-0d5b15880752.jpg', - 'api': 'https://api.vaultoro.com', - 'www': 'https://www.vaultoro.com', - 'doc': 'https://api.vaultoro.com', - }, - 'commonCurrencies': { - 'GLD': 'Gold', - }, - 'api': { - 'public': { - 'get': [ - 'bidandask', - 'buyorders', - 'latest', - 'latesttrades', - 'markets', - 'orderbook', - 'sellorders', - 'transactions/day', - 'transactions/hour', - 'transactions/month', - ], - }, - 'private': { - 'get': [ - 'balance', - 'mytrades', - 'orders', - ], - 'post': [ - 'buy/{symbol}/{type}', - 'cancel/{id}', - 'sell/{symbol}/{type}', - 'withdraw', - ], - }, - }, - }); - } - - async fetchMarkets (params = {}) { - const result = []; - const response = await this.publicGetMarkets (params); - const market = this.safeValue (response, 'data'); - const baseId = this.safeString (market, 'MarketCurrency'); - const quoteId = this.safeString (market, 'BaseCurrency'); - const base = this.safeCurrencyCode (baseId); - const quote = this.safeCurrencyCode (quoteId); - const symbol = base + '/' + quote; - const id = this.safeString (market, 'MarketName'); - result.push ({ - 'id': id, - 'symbol': symbol, - 'base': base, - 'quote': quote, - 'baseId': baseId, - 'quoteId': quoteId, - 'info': market, - 'active': undefined, - 'precision': this.precision, - 'limits': this.limits, - }); - return result; - } - - async fetchBalance (params = {}) { - await this.loadMarkets (); - const response = await this.privateGetBalance (params); - const balances = this.safeValue (response, 'data'); - const result = { 'info': balances }; - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - const currencyId = this.safeString (balance, 'currency_code'); - const code = this.safeCurrencyCode (currencyId); - const account = this.account (); - account['free'] = this.safeFloat (balance, 'cash'); - account['used'] = this.safeFloat (balance, 'reserved'); - result[code] = account; - } - return this.parseBalance (result); - } - - async fetchOrderBook (symbol, limit = undefined, params = {}) { - await this.loadMarkets (); - const response = await this.publicGetOrderbook (params); - const orderbook = { - 'bids': response['data'][0]['b'], - 'asks': response['data'][1]['s'], - }; - return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'Gold_Price', 'Gold_Amount'); - } - - parseTrade (trade, market = undefined) { - const timestamp = this.parse8601 (this.safeString (trade, 'Time')); - let symbol = undefined; - if (market !== undefined) { - symbol = market['symbol']; - } - const price = this.safeFloat (trade, 'Gold_Price'); - const amount = this.safeFloat (trade, 'Gold_Amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } - return { - 'id': undefined, - 'info': trade, - 'timestamp': timestamp, - 'datetime': this.iso8601 (timestamp), - 'symbol': symbol, - 'order': undefined, - 'type': undefined, - 'side': undefined, - 'takerOrMaker': undefined, - 'price': price, - 'amount': amount, - 'cost': cost, - 'fee': undefined, - }; - } - - async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const response = await this.publicGetTransactionsDay (params); - return this.parseTrades (response, market, since, limit); - } - - async createOrder (symbol, type, side, amount, price = undefined, params = {}) { - await this.loadMarkets (); - const market = this.market (symbol); - const method = 'privatePost' + this.capitalize (side) + 'SymbolType'; - const request = { - 'symbol': market['quoteId'].toLowerCase (), - 'type': type, - 'gld': amount, - 'price': price || 1, - }; - const response = await this[method] (this.extend (request, params)); - return { - 'info': response, - 'id': response['data']['Order_ID'], - }; - } - - async cancelOrder (id, symbol = undefined, params = {}) { - await this.loadMarkets (); - const request = { - 'id': id, - }; - return await this.privatePostCancelId (this.extend (request, params)); - } - - sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { - let url = this.urls['api'] + '/'; - if (api === 'public') { - url += path; - } else { - this.checkRequiredCredentials (); - const nonce = this.nonce (); - url += this.version + '/' + this.implodeParams (path, params); - const query = this.extend ({ - 'nonce': nonce, - 'apikey': this.apiKey, - }, this.omit (params, this.extractParams (path))); - url += '?' + this.urlencode (query); - headers = { - 'Content-Type': 'application/json', - 'X-Signature': this.hmac (this.encode (url), this.encode (this.secret)), - }; - } - return { 'url': url, 'method': method, 'body': body, 'headers': headers }; - } -}; diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vcc.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vcc.js index bd3a9602d..5b182adcb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vcc.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/vcc.js @@ -5,6 +5,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, OrderNotFound, InvalidOrder, BadRequest, AuthenticationError, RateLimitExceeded, RequestTimeout, BadSymbol, AddressPending, PermissionDenied, InsufficientFunds } = require ('./base/errors'); const { ROUND } = require ('./base/functions/number'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -196,15 +197,15 @@ module.exports = class vcc extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (amountLimits, 'min'), + 'min': this.safeNumber (amountLimits, 'min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (priceLimits, 'min'), + 'min': this.safeNumber (priceLimits, 'min'), 'max': undefined, }, 'cost': { - 'min': this.safeFloat (costLimits, 'min'), + 'min': this.safeNumber (costLimits, 'min'), 'max': undefined, }, }, @@ -251,12 +252,12 @@ module.exports = class vcc extends Exchange { 'code': code, 'name': this.safeString (currency, 'name'), 'active': active, - 'fee': this.safeFloat (currency, 'withdrawal_fee'), + 'fee': this.safeNumber (currency, 'withdrawal_fee'), 'precision': this.safeInteger (currency, 'decimal'), 'limits': { 'withdraw': { - 'min': this.safeFloat (currency, 'min_withdraw'), - 'max': this.safeFloat (currency, 'max_withdraw'), + 'min': this.safeNumber (currency, 'min_withdraw'), + 'max': this.safeNumber (currency, 'max_withdraw'), }, }, }; @@ -279,8 +280,8 @@ module.exports = class vcc extends Exchange { // return { 'info': response, - 'maker': this.safeFloat (response, 'provideLiquidityRate'), - 'taker': this.safeFloat (response, 'takeLiquidityRate'), + 'maker': this.safeNumber (response, 'provideLiquidityRate'), + 'taker': this.safeNumber (response, 'takeLiquidityRate'), }; } @@ -306,11 +307,11 @@ module.exports = class vcc extends Exchange { const code = this.safeCurrencyCode (currencyId); const balance = this.safeValue (data, currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available_balance'); - account['total'] = this.safeFloat (balance, 'balance'); + account['free'] = this.safeString (balance, 'available_balance'); + account['total'] = this.safeString (balance, 'balance'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseOHLCV (ohlcv, market = undefined) { @@ -328,11 +329,11 @@ module.exports = class vcc extends Exchange { // return [ this.safeInteger (ohlcv, 'time'), - this.safeFloat (ohlcv, 'open'), - this.safeFloat (ohlcv, 'high'), - this.safeFloat (ohlcv, 'low'), - this.safeFloat (ohlcv, 'close'), - this.safeFloat (ohlcv, 'volume'), + this.safeNumber (ohlcv, 'open'), + this.safeNumber (ohlcv, 'high'), + this.safeNumber (ohlcv, 'low'), + this.safeNumber (ohlcv, 'close'), + this.safeNumber (ohlcv, 'volume'), ]; } @@ -421,10 +422,10 @@ module.exports = class vcc extends Exchange { // } // const timestamp = this.milliseconds (); - const baseVolume = this.safeFloat (ticker, 'base_volume'); - const quoteVolume = this.safeFloat (ticker, 'quote_volume'); - const open = this.safeFloat (ticker, 'open_price'); - const last = this.safeFloat (ticker, 'last_price'); + const baseVolume = this.safeNumber (ticker, 'base_volume'); + const quoteVolume = this.safeNumber (ticker, 'quote_volume'); + const open = this.safeNumber (ticker, 'open_price'); + const last = this.safeNumber (ticker, 'last_price'); let change = undefined; let percentage = undefined; let average = undefined; @@ -441,11 +442,11 @@ module.exports = class vcc extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'max_price'), - 'low': this.safeFloat (ticker, 'min_price'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'max_price'), + 'low': this.safeNumber (ticker, 'min_price'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': open, @@ -559,17 +560,17 @@ module.exports = class vcc extends Exchange { } market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'base_volume', 'quantity'); - let cost = this.safeFloat2 (trade, 'quote_volume', 'amount'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'base_volume', 'quantity'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + let cost = this.safeNumber2 (trade, 'quote_volume', 'amount'); if (cost === undefined) { - if ((price !== undefined) && (amount !== undefined)) { - cost = price * amount; - } + cost = this.parseNumber (Precise.stringMul (priceString, amountString)); } const side = this.safeString2 (trade, 'type', 'trade_type'); const id = this.safeString2 (trade, 'trade_id', 'id'); - const feeCost = this.safeFloat (trade, 'fee'); + const feeCost = this.safeNumber (trade, 'fee'); let fee = undefined; if (feeCost !== undefined) { fee = { @@ -754,7 +755,7 @@ module.exports = class vcc extends Exchange { const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId, currency); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); - let amount = this.safeFloat (transaction, 'amount'); + let amount = this.safeNumber (transaction, 'amount'); if (amount !== undefined) { amount = Math.abs (amount); } @@ -762,7 +763,7 @@ module.exports = class vcc extends Exchange { const txid = this.safeString (transaction, 'transaction_id'); const tag = this.safeString (transaction, 'destination_tag'); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fee'); + const feeCost = this.safeNumber (transaction, 'fee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -1007,46 +1008,27 @@ module.exports = class vcc extends Exchange { const marketId = baseId + '_' + quoteId; market = this.safeMarket (marketId, market, '_'); const symbol = market['symbol']; - const amount = this.safeFloat (order, 'quantity'); - let filled = this.safeFloat (order, 'executed_quantity'); + const amount = this.safeNumber (order, 'quantity'); + const filled = this.safeNumber (order, 'executed_quantity'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - let cost = this.safeFloat (order, 'ceiling'); + const cost = this.safeNumber (order, 'ceiling'); const id = this.safeString (order, 'id'); - let average = undefined; - let price = this.safeFloat (order, 'price'); - // in case of market order - if (!price) { - price = this.safeFloat (order, 'executed_price'); - average = price; - } - let remaining = this.safeFloat (order, 'remaining'); - if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) { - filled = Math.max (0, amount - remaining); - } - if (filled !== undefined) { - if ((amount !== undefined) && (remaining === undefined)) { - remaining = Math.max (0, amount - filled); - } - if ((price !== undefined) && (cost === undefined)) { - cost = filled * price; - } - if ((average === undefined) && (cost !== undefined) && (filled > 0)) { - average = cost / filled; - } - } + const price = this.safeNumber (order, 'price'); + const average = this.safeNumber (order, 'executed_price'); + const remaining = this.safeNumber (order, 'remaining'); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'trade_type'); const fee = { 'currency': market['quote'], - 'cost': this.safeFloat (order, 'fee'), - 'rate': this.safeFloat (order, 'fee_rate'), + 'cost': this.safeNumber (order, 'fee'), + 'rate': this.safeNumber (order, 'fee_rate'), }; let lastTradeTimestamp = undefined; if (updated !== created) { lastTradeTimestamp = updated; } - const stopPrice = this.safeFloat (order, 'stopPrice'); - return { + const stopPrice = this.safeNumber (order, 'stopPrice'); + return this.safeOrder ({ 'id': id, 'clientOrderId': id, 'timestamp': created, @@ -1068,7 +1050,7 @@ module.exports = class vcc extends Exchange { 'fee': fee, 'trades': undefined, 'info': order, - }; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/wavesexchange.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/wavesexchange.js index 139780062..bd422c073 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/wavesexchange.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/wavesexchange.js @@ -565,13 +565,13 @@ module.exports = class wavesexchange extends Exchange { symbol = market['symbol']; } const data = this.safeValue (ticker, 'data', {}); - const last = this.safeFloat (data, 'lastPrice'); - const low = this.safeFloat (data, 'low'); - const high = this.safeFloat (data, 'high'); - const vwap = this.safeFloat (data, 'weightedAveragePrice'); - const baseVolume = this.safeFloat (data, 'volume'); - const quoteVolume = this.safeFloat (data, 'quoteVolume'); - const open = this.safeValue (data, 'firstPrice'); + const last = this.safeNumber (data, 'lastPrice'); + const low = this.safeNumber (data, 'low'); + const high = this.safeNumber (data, 'high'); + const vwap = this.safeNumber (data, 'weightedAveragePrice'); + const baseVolume = this.safeNumber (data, 'volume'); + const quoteVolume = this.safeNumber (data, 'quoteVolume'); + const open = this.safeNumber (data, 'firstPrice'); let change = undefined; let average = undefined; let percentage = undefined; @@ -725,11 +725,11 @@ module.exports = class wavesexchange extends Exchange { const data = this.safeValue (ohlcv, 'data', {}); return [ this.parse8601 (this.safeString (data, 'time')), - this.safeFloat (data, 'open'), - this.safeFloat (data, 'high'), - this.safeFloat (data, 'low'), - this.safeFloat (data, 'close'), - this.safeFloat (data, 'volume', 0), + this.safeNumber (data, 'open'), + this.safeNumber (data, 'high'), + this.safeNumber (data, 'low'), + this.safeNumber (data, 'close'), + this.safeNumber (data, 'volume', 0), ]; } @@ -944,7 +944,7 @@ module.exports = class wavesexchange extends Exchange { } if (matcherFee === undefined) { const wavesPrecision = this.safeInteger (this.options, 'wavesPrecision', 8); - const rate = this.safeFloat (rates, matcherFeeAssetId); + const rate = this.safeNumber (rates, matcherFeeAssetId); const code = this.safeCurrencyCode (matcherFeeAssetId); const currency = this.currency (code); const newPrecison = Math.pow (10, wavesPrecision - currency['precision']); @@ -1354,7 +1354,7 @@ module.exports = class wavesexchange extends Exchange { const issueTransaction = this.safeValue (entry, 'issueTransaction'); const decimals = this.safeInteger (issueTransaction, 'decimals'); const currencyId = this.safeString (entry, 'assetId'); - const balance = this.safeFloat (entry, 'balance'); + const balance = this.safeNumber (entry, 'balance'); let code = undefined; if (currencyId in this.currencies_by_id) { code = this.safeCurrencyCode (currencyId); @@ -1384,7 +1384,7 @@ module.exports = class wavesexchange extends Exchange { if (!(code in result)) { result[code] = this.account (); } - const amount = this.safeFloat (reservedBalance, currencyId); + const amount = this.safeNumber (reservedBalance, currencyId); result[code]['used'] = this.currencyFromPrecision (code, amount); } const wavesRequest = { @@ -1397,7 +1397,7 @@ module.exports = class wavesexchange extends Exchange { // "balance": 909085978 // } result['WAVES'] = this.safeValue (result, 'WAVES', {}); - result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeFloat (wavesTotal, 'balance')); + result['WAVES']['total'] = this.currencyFromPrecision ('WAVES', this.safeNumber (wavesTotal, 'balance')); const codes = Object.keys (result); for (let i = 0; i < codes.length; i++) { const code = codes[i]; @@ -1489,8 +1489,8 @@ module.exports = class wavesexchange extends Exchange { const datetime = this.safeString (data, 'timestamp'); const timestamp = this.parse8601 (datetime); const id = this.safeString (data, 'id'); - const price = this.safeFloat (data, 'price'); - const amount = this.safeFloat (data, 'amount'); + const price = this.safeNumber (data, 'price'); + const amount = this.safeNumber (data, 'amount'); const order1 = this.safeValue (data, 'order1'); const order2 = this.safeValue (data, 'order2'); let order = undefined; @@ -1514,7 +1514,7 @@ module.exports = class wavesexchange extends Exchange { cost = price * amount; } const fee = { - 'cost': this.safeFloat (data, 'fee'), + 'cost': this.safeNumber (data, 'fee'), 'currency': this.safeCurrencyCode (this.safeString (order, 'matcherFeeAssetId', 'WAVES')), }; return { @@ -1596,7 +1596,7 @@ module.exports = class wavesexchange extends Exchange { const withdrawAddress = await this.privateGetWithdrawAddressesCurrencyAddress (withdrawAddressRequest); const currency = this.safeValue (withdrawAddress, 'currency'); const allowedAmount = this.safeValue (currency, 'allowed_amount'); - const minimum = this.safeFloat (allowedAmount, 'min'); + const minimum = this.safeNumber (allowedAmount, 'min'); if (amount <= minimum) { throw new BadRequest (this.id + ' ' + code + ' withdraw failed, amount ' + amount.toString () + ' must be greater than the minimum allowed amount of ' + minimum.toString ()); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/whitebit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/whitebit.js index 9e4418141..769cd5b8b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/whitebit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/whitebit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeNotAvailable, ExchangeError, DDoSProtection, BadSymbol } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -164,7 +165,7 @@ module.exports = class whitebit extends Exchange { }, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'minAmount'), + 'min': this.safeNumber (market, 'minAmount'), 'max': undefined, }, 'price': { @@ -172,7 +173,7 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'cost': { - 'min': this.safeFloat (market, 'minTotal'), + 'min': this.safeNumber (market, 'minTotal'), 'max': undefined, }, }, @@ -237,8 +238,8 @@ module.exports = class whitebit extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (currency, 'minWithdrawal'), - 'max': this.safeFloat (currency, 'maxWithdrawal'), + 'min': this.safeNumber (currency, 'minWithdrawal'), + 'max': this.safeNumber (currency, 'maxWithdrawal'), }, }, }; @@ -250,8 +251,8 @@ module.exports = class whitebit extends Exchange { const response = await this.publicV2GetFee (params); const fees = this.safeValue (response, 'result'); return { - 'maker': this.safeFloat (fees, 'makerFee'), - 'taker': this.safeFloat (fees, 'takerFee'), + 'maker': this.safeNumber (fees, 'makerFee'), + 'taker': this.safeNumber (fees, 'takerFee'), }; } @@ -321,8 +322,8 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); - const percentage = this.safeFloat (ticker, 'change'); + const last = this.safeNumber (ticker, 'last'); + const percentage = this.safeNumber (ticker, 'change'); let change = undefined; if (percentage !== undefined) { change = this.numberToString (percentage * 0.01); @@ -331,22 +332,22 @@ module.exports = class whitebit extends Exchange { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, - 'open': this.safeFloat (ticker, 'open'), + 'open': this.safeNumber (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': change, 'percentage': percentage, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'volume'), - 'quoteVolume': this.safeFloat (ticker, 'deal'), + 'baseVolume': this.safeNumber (ticker, 'volume'), + 'quoteVolume': this.safeNumber (ticker, 'deal'), 'info': ticker, }; } @@ -514,8 +515,11 @@ module.exports = class whitebit extends Exchange { } else { timestamp = parseInt (timestamp * 1000); } - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat2 (trade, 'amount', 'volume'); + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString2 (trade, 'amount', 'volume'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const id = this.safeString2 (trade, 'id', 'tradeId'); let side = this.safeString (trade, 'type'); if (side === undefined) { @@ -526,10 +530,6 @@ module.exports = class whitebit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - let cost = undefined; - if (amount !== undefined && price !== undefined) { - cost = amount * price; - } return { 'info': trade, 'timestamp': timestamp, @@ -599,11 +599,11 @@ module.exports = class whitebit extends Exchange { // return [ this.safeTimestamp (ohlcv, 0), // timestamp - this.safeFloat (ohlcv, 1), // open - this.safeFloat (ohlcv, 3), // high - this.safeFloat (ohlcv, 4), // low - this.safeFloat (ohlcv, 2), // close - this.safeFloat (ohlcv, 5), // volume + this.safeNumber (ohlcv, 1), // open + this.safeNumber (ohlcv, 3), // high + this.safeNumber (ohlcv, 4), // low + this.safeNumber (ohlcv, 2), // close + this.safeNumber (ohlcv, 5), // volume ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xbtce.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xbtce.js index e0d137f67..c8cabae42 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xbtce.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xbtce.js @@ -152,14 +152,13 @@ module.exports = class xbtce extends Exchange { const balance = balances[i]; const currencyId = this.safeString (balance, 'Currency'); const code = this.safeCurrencyCode (currencyId); - const account = { - 'free': this.safeFloat (balance, 'FreeAmount'), - 'used': this.safeFloat (balance, 'LockedAmount'), - 'total': this.safeFloat (balance, 'Amount'), - }; + const account = this.account (); + account['free'] = this.safeString (balance, 'FreeAmount'); + account['used'] = this.safeString (balance, 'LockedAmount'); + account['total'] = this.safeString (balance, 'Amount'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchOrderBook (symbol, limit = undefined, params = {}) { @@ -271,11 +270,11 @@ module.exports = class xbtce extends Exchange { parseOHLCV (ohlcv, market = undefined) { return [ this.safeInteger (ohlcv, 'Timestamp'), - this.safeFloat (ohlcv, 'Open'), - this.safeFloat (ohlcv, 'High'), - this.safeFloat (ohlcv, 'Low'), - this.safeFloat (ohlcv, 'Close'), - this.safeFloat (ohlcv, 'Volume'), + this.safeNumber (ohlcv, 'Open'), + this.safeNumber (ohlcv, 'High'), + this.safeNumber (ohlcv, 'Low'), + this.safeNumber (ohlcv, 'Close'), + this.safeNumber (ohlcv, 'Volume'), ]; } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xena.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xena.js index 2facd429b..e55a5332b 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xena.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/xena.js @@ -2,6 +2,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, InsufficientFunds, InvalidAddress, BadSymbol, InvalidOrder } = require ('./base/errors'); +const Precise = require ('./base/Precise'); module.exports = class xena extends Exchange { describe () { @@ -277,8 +278,8 @@ module.exports = class xena extends Exchange { 'price': pricePrecision, 'amount': 0, }; - const maxCost = this.safeFloat (market, 'maxOrderQty'); - const minCost = this.safeFloat (market, 'minOrderQuantity'); + const maxCost = this.safeNumber (market, 'maxOrderQty'); + const minCost = this.safeNumber (market, 'minOrderQuantity'); const limits = { 'amount': { 'min': undefined, @@ -363,7 +364,7 @@ module.exports = class xena extends Exchange { 'info': currency, 'name': name, 'active': active, - 'fee': this.safeFloat (withdraw, 'commission'), + 'fee': this.safeNumber (withdraw, 'commission'), 'precision': precision, 'limits': { 'amount': { @@ -379,7 +380,7 @@ module.exports = class xena extends Exchange { 'max': undefined, }, 'withdraw': { - 'min': this.safeFloat (withdraw, 'minAmount'), + 'min': this.safeNumber (withdraw, 'minAmount'), 'max': undefined, }, }, @@ -407,8 +408,8 @@ module.exports = class xena extends Exchange { const timestamp = this.milliseconds (); const marketId = this.safeString (ticker, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const last = this.safeFloat (ticker, 'lastPx'); - const open = this.safeFloat (ticker, 'firstPx'); + const last = this.safeNumber (ticker, 'lastPx'); + const open = this.safeNumber (ticker, 'firstPx'); let percentage = undefined; let change = undefined; let average = undefined; @@ -419,18 +420,18 @@ module.exports = class xena extends Exchange { percentage = change / open * 100; } } - const buyVolume = this.safeFloat (ticker, 'buyVolume'); - const sellVolume = this.safeFloat (ticker, 'sellVolume'); + const buyVolume = this.safeNumber (ticker, 'buyVolume'); + const sellVolume = this.safeNumber (ticker, 'sellVolume'); const baseVolume = this.sum (buyVolume, sellVolume); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'highPx'), - 'low': this.safeFloat (ticker, 'lowPx'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'highPx'), + 'low': this.safeNumber (ticker, 'lowPx'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, @@ -607,11 +608,11 @@ module.exports = class xena extends Exchange { const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'onHold'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'onHold'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseTrade (trade, market = undefined) { @@ -665,20 +666,17 @@ module.exports = class xena extends Exchange { const orderId = this.safeString (trade, 'orderId'); const marketId = this.safeString (trade, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat2 (trade, 'lastPx', 'mdEntryPx'); - const amount = this.safeFloat2 (trade, 'lastQty', 'mdEntrySize'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString2 (trade, 'lastPx', 'mdEntryPx'); + const amountString = this.safeString2 (trade, 'lastQty', 'mdEntrySize'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); - const feeRate = this.safeFloat (trade, 'commRate'); + const feeRate = this.safeNumber (trade, 'commRate'); fee = { 'cost': feeCost, 'rate': feeRate, @@ -793,15 +791,15 @@ module.exports = class xena extends Exchange { // const transactTime = this.safeInteger (ohlcv, 'transactTime'); const timestamp = parseInt (transactTime / 1000000); - const buyVolume = this.safeFloat (ohlcv, 'buyVolume'); - const sellVolume = this.safeFloat (ohlcv, 'sellVolume'); + const buyVolume = this.safeNumber (ohlcv, 'buyVolume'); + const sellVolume = this.safeNumber (ohlcv, 'sellVolume'); const volume = this.sum (buyVolume, sellVolume); return [ timestamp, - this.safeFloat (ohlcv, 'firstPx'), - this.safeFloat (ohlcv, 'highPx'), - this.safeFloat (ohlcv, 'lowPx'), - this.safeFloat (ohlcv, 'lastPx'), + this.safeNumber (ohlcv, 'firstPx'), + this.safeNumber (ohlcv, 'highPx'), + this.safeNumber (ohlcv, 'lowPx'), + this.safeNumber (ohlcv, 'lastPx'), volume, ]; } @@ -926,11 +924,10 @@ module.exports = class xena extends Exchange { const status = this.parseOrderStatus (this.safeString (order, 'ordStatus')); const marketId = this.safeString (order, 'symbol'); const symbol = this.safeSymbol (marketId, market); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'orderQty'); - const filled = this.safeFloat (order, 'cumQty'); - const remaining = this.safeFloat (order, 'leavesQty'); - let cost = undefined; + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'orderQty'); + const filled = this.safeNumber (order, 'cumQty'); + const remaining = this.safeNumber (order, 'leavesQty'); let side = this.safeStringLower (order, 'side'); if (side === '1') { side = 'buy'; @@ -947,12 +944,7 @@ module.exports = class xena extends Exchange { } else if (type === '4') { type = 'stop-limit'; } - if (cost === undefined) { - if ((price !== undefined) && (filled !== undefined)) { - cost = price * filled; - } - } - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': clientOrderId, 'info': order, @@ -967,14 +959,14 @@ module.exports = class xena extends Exchange { 'price': price, 'stopPrice': undefined, 'amount': amount, - 'cost': cost, + 'cost': undefined, 'average': undefined, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': undefined, 'trades': undefined, - }; + }); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { @@ -1027,7 +1019,7 @@ module.exports = class xena extends Exchange { request['price'] = this.priceToPrecision (symbol, price); } if ((type === 'stop') || (type === 'stop-limit')) { - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx === undefined) { throw new InvalidOrder (this.id + ' createOrder() requires a stopPx param for order type ' + type); } @@ -1106,12 +1098,12 @@ module.exports = class xena extends Exchange { if (price !== undefined) { request['price'] = this.priceToPrecision (symbol, price); } - const stopPx = this.safeFloat (params, 'stopPx'); + const stopPx = this.safeNumber (params, 'stopPx'); if (stopPx !== undefined) { request['stopPx'] = this.priceToPrecision (symbol, stopPx); params = this.omit (params, 'stopPx'); } - const capPrice = this.safeFloat (params, 'capPrice'); + const capPrice = this.safeNumber (params, 'capPrice'); if (capPrice !== undefined) { request['capPrice'] = this.priceToPrecision (symbol, capPrice); params = this.omit (params, 'capPrice'); @@ -1466,7 +1458,7 @@ module.exports = class xena extends Exchange { const address = this.safeString (transaction, 'address'); const addressFrom = undefined; const addressTo = address; - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const fee = undefined; return { @@ -1563,7 +1555,7 @@ module.exports = class xena extends Exchange { const referenceAccount = undefined; const type = this.parseLedgerEntryType (this.safeString (item, 'kind')); const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency); - let amount = this.safeFloat (item, 'amount'); + let amount = this.safeNumber (item, 'amount'); if (amount < 0) { direction = 'out'; amount = Math.abs (amount); @@ -1575,11 +1567,11 @@ module.exports = class xena extends Exchange { timestamp = parseInt (timestamp / 1000000); } const fee = { - 'cost': this.safeFloat (item, 'commission'), + 'cost': this.safeNumber (item, 'commission'), 'currency': code, }; const before = undefined; - const after = this.safeFloat (item, 'balance'); + const after = this.safeNumber (item, 'balance'); const status = 'ok'; return { 'info': item, diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/yobit.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/yobit.js index 0ab100f68..82d86ea71 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/yobit.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/yobit.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InvalidNonce, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError, RateLimitExceeded } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -138,6 +139,7 @@ module.exports = class yobit extends Exchange { 'NAV': 'NavajoCoin', 'NBT': 'NiceBytes', 'OMG': 'OMGame', + 'ONX': 'Onix', 'PAC': '$PAC', 'PLAY': 'PlayCoin', 'PIVX': 'Darknet', @@ -236,15 +238,33 @@ module.exports = class yobit extends Exchange { const currencyId = currencyIds[i]; const code = this.safeCurrencyCode (currencyId); const account = this.account (); - account['free'] = this.safeFloat (free, currencyId); - account['total'] = this.safeFloat (total, currencyId); + account['free'] = this.safeString (free, currencyId); + account['total'] = this.safeString (total, currencyId); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } async fetchMarkets (params = {}) { const response = await this.publicGetInfo (params); + // + // { + // "server_time":1615856752, + // "pairs":{ + // "ltc_btc":{ + // "decimal_places":8, + // "min_price":0.00000001, + // "max_price":10000, + // "min_amount":0.0001, + // "min_total":0.0001, + // "hidden":0, + // "fee":0.2, + // "fee_buyer":0.2, + // "fee_seller":0.2 + // }, + // }, + // } + // const markets = this.safeValue (response, 'pairs'); const keys = Object.keys (markets); const result = []; @@ -262,15 +282,15 @@ module.exports = class yobit extends Exchange { 'price': this.safeInteger (market, 'decimal_places'), }; const amountLimits = { - 'min': this.safeFloat (market, 'min_amount'), - 'max': this.safeFloat (market, 'max_amount'), + 'min': this.safeNumber (market, 'min_amount'), + 'max': this.safeNumber (market, 'max_amount'), }; const priceLimits = { - 'min': this.safeFloat (market, 'min_price'), - 'max': this.safeFloat (market, 'max_price'), + 'min': this.safeNumber (market, 'min_price'), + 'max': this.safeNumber (market, 'max_price'), }; const costLimits = { - 'min': this.safeFloat (market, 'min_total'), + 'min': this.safeNumber (market, 'min_total'), }; const limits = { 'amount': amountLimits, @@ -279,6 +299,7 @@ module.exports = class yobit extends Exchange { }; const hidden = this.safeInteger (market, 'hidden'); const active = (hidden === 0); + const takerFee = this.safeNumber (market, 'fee'); result.push ({ 'id': id, 'symbol': symbol, @@ -287,7 +308,7 @@ module.exports = class yobit extends Exchange { 'baseId': baseId, 'quoteId': quoteId, 'active': active, - 'taker': market['fee'] / 100, + 'taker': takerFee / 100, 'precision': precision, 'limits': limits, 'info': market, @@ -363,16 +384,16 @@ module.exports = class yobit extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -381,9 +402,9 @@ module.exports = class yobit extends Exchange { 'previousClose': undefined, 'change': undefined, 'percentage': undefined, - 'average': this.safeFloat (ticker, 'avg'), - 'baseVolume': this.safeFloat (ticker, 'vol_cur'), - 'quoteVolume': this.safeFloat (ticker, 'vol'), + 'average': this.safeNumber (ticker, 'avg'), + 'baseVolume': this.safeNumber (ticker, 'vol_cur'), + 'quoteVolume': this.safeNumber (ticker, 'vol'), 'info': ticker, }; } @@ -432,15 +453,18 @@ module.exports = class yobit extends Exchange { } else if (side === 'bid') { side = 'buy'; } - const price = this.safeFloat2 (trade, 'rate', 'price'); + const priceString = this.safeString2 (trade, 'rate', 'price'); const id = this.safeString2 (trade, 'trade_id', 'tid'); const order = this.safeString (trade, 'order_id'); const marketId = this.safeString (trade, 'pair'); const symbol = this.safeSymbol (marketId, market); - const amount = this.safeFloat (trade, 'amount'); + const amountString = this.safeString (trade, 'amount'); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); const type = 'limit'; // all trades are still limit trades let fee = undefined; - const feeCost = this.safeFloat (trade, 'commission'); + const feeCost = this.safeNumber (trade, 'commission'); if (feeCost !== undefined) { const feeCurrencyId = this.safeString (trade, 'commissionCurrency'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); @@ -455,12 +479,6 @@ module.exports = class yobit extends Exchange { fee = this.calculateFee (symbol, type, side, amount, price, 'taker'); } } - let cost = undefined; - if (amount !== undefined) { - if (price !== undefined) { - cost = amount * price; - } - } return { 'id': id, 'order': order, @@ -522,8 +540,8 @@ module.exports = class yobit extends Exchange { id = this.safeString (response['return'], 'init_order_id'); status = 'closed'; } - filled = this.safeFloat (response['return'], 'received', 0.0); - remaining = this.safeFloat (response['return'], 'remains', amount); + filled = this.safeNumber (response['return'], 'received', 0.0); + remaining = this.safeNumber (response['return'], 'remains', amount); } const timestamp = this.milliseconds (); return { @@ -573,21 +591,13 @@ module.exports = class yobit extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp_created'); const marketId = this.safeString (order, 'pair'); const symbol = this.safeSymbol (marketId, market); - const remaining = this.safeFloat (order, 'amount'); - const amount = this.safeFloat (order, 'start_amount'); - const price = this.safeFloat (order, 'rate'); - let filled = undefined; - let cost = undefined; - if (amount !== undefined) { - if (remaining !== undefined) { - filled = Math.max (0, amount - remaining); - cost = price * filled; - } - } + const remaining = this.safeNumber (order, 'amount'); + const amount = this.safeNumber (order, 'start_amount'); + const price = this.safeNumber (order, 'rate'); const fee = undefined; const type = 'limit'; const side = this.safeString (order, 'type'); - const result = { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -601,16 +611,15 @@ module.exports = class yobit extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'remaining': remaining, - 'filled': filled, + 'filled': undefined, 'status': status, 'fee': fee, 'average': undefined, 'trades': undefined, - }; - return result; + }); } async fetchOrder (id, symbol = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zaif.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zaif.js index 2c6454a05..a94f9dddb 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zaif.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zaif.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { ExchangeError, BadRequest } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -127,6 +128,27 @@ module.exports = class zaif extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetCurrencyPairsAll (params); + // + // [ + // { + // "aux_unit_point": 0, + // "item_japanese": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3", + // "aux_unit_step": 5.0, + // "description": "\u30d3\u30c3\u30c8\u30b3\u30a4\u30f3\u30fb\u65e5\u672c\u5186\u306e\u53d6\u5f15\u3092\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059", + // "item_unit_min": 0.001, + // "event_number": 0, + // "currency_pair": "btc_jpy", + // "is_token": false, + // "aux_unit_min": 5.0, + // "aux_japanese": "\u65e5\u672c\u5186", + // "id": 1, + // "item_unit_step": 0.0001, + // "name": "BTC/JPY", + // "seq": 0, + // "title": "BTC/JPY" + // } + // ] + // const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; @@ -137,8 +159,8 @@ module.exports = class zaif extends Exchange { const quote = this.safeCurrencyCode (quoteId); const symbol = base + '/' + quote; const precision = { - 'amount': -Math.log10 (market['item_unit_step']), - 'price': market['aux_unit_point'], + 'amount': -Math.log10 (this.safeNumber (market, 'item_unit_step')), + 'price': this.safeInteger (market, 'aux_unit_point'), }; const fees = this.safeValue (this.options['fees'], symbol, this.fees['trading']); const taker = fees['taker']; @@ -156,11 +178,11 @@ module.exports = class zaif extends Exchange { 'maker': maker, 'limits': { 'amount': { - 'min': this.safeFloat (market, 'item_unit_min'), + 'min': this.safeNumber (market, 'item_unit_min'), 'max': undefined, }, 'price': { - 'min': this.safeFloat (market, 'aux_unit_min'), + 'min': this.safeNumber (market, 'aux_unit_min'), 'max': undefined, }, 'cost': { @@ -192,7 +214,7 @@ module.exports = class zaif extends Exchange { }; if ('deposit' in balances) { if (currencyId in balances['deposit']) { - account['total'] = this.safeFloat (balances['deposit'], currencyId); + account['total'] = this.safeNumber (balances['deposit'], currencyId); account['used'] = account['total'] - account['free']; } } @@ -217,22 +239,22 @@ module.exports = class zaif extends Exchange { }; const ticker = await this.publicGetTickerPair (this.extend (request, params)); const timestamp = this.milliseconds (); - const vwap = this.safeFloat (ticker, 'vwap'); - const baseVolume = this.safeFloat (ticker, 'volume'); + const vwap = this.safeNumber (ticker, 'vwap'); + const baseVolume = this.safeNumber (ticker, 'volume'); let quoteVolume = undefined; if (baseVolume !== undefined && vwap !== undefined) { quoteVolume = baseVolume * vwap; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'bid'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'bid'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'ask'), + 'ask': this.safeNumber (ticker, 'ask'), 'askVolume': undefined, 'vwap': vwap, 'open': undefined, @@ -253,14 +275,11 @@ module.exports = class zaif extends Exchange { side = (side === 'bid') ? 'buy' : 'sell'; const timestamp = this.safeTimestamp (trade, 'date'); const id = this.safeString2 (trade, 'id', 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = amount * price; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (Precise.stringMul (priceString, amountString)); const marketId = this.safeString (trade, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); return { @@ -338,16 +357,10 @@ module.exports = class zaif extends Exchange { const timestamp = this.safeTimestamp (order, 'timestamp'); const marketId = this.safeString (order, 'currency_pair'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const amount = this.safeFloat (order, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const price = this.safeNumber (order, 'price'); + const amount = this.safeNumber (order, 'amount'); const id = this.safeString (order, 'id'); - return { + return this.safeOrder ({ 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, @@ -361,7 +374,7 @@ module.exports = class zaif extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'cost': cost, + 'cost': undefined, 'amount': amount, 'filled': undefined, 'remaining': undefined, @@ -369,7 +382,7 @@ module.exports = class zaif extends Exchange { 'fee': undefined, 'info': order, 'average': undefined, - }; + }); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zb.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zb.js index 1f8f61cdf..29bea651d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zb.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/js/zb.js @@ -4,6 +4,7 @@ const Exchange = require ('./base/Exchange'); const { BadRequest, ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, OrderNotFound, ExchangeNotAvailable, DDoSProtection, InvalidOrder, InvalidAddress } = require ('./base/errors'); +const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- @@ -89,8 +90,8 @@ module.exports = class zb extends Exchange { 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg', 'api': { - 'public': 'http://api.zb.cn/data', // no https for public API - 'private': 'https://trade.zb.cn/api', + 'public': 'https://api.zb.today/data', + 'private': 'https://trade.zb.today/api', }, 'www': 'https://www.zb.com', 'doc': 'https://www.zb.com/i/developer', @@ -205,6 +206,16 @@ module.exports = class zb extends Exchange { async fetchMarkets (params = {}) { const markets = await this.publicGetMarkets (params); + // + // { + // "zb_qc":{ + // "amountScale":2, + // "minAmount":0.01, + // "minSize":5, + // "priceScale":4, + // }, + // } + // const keys = Object.keys (markets); const result = []; for (let i = 0; i < keys.length; i++) { @@ -268,11 +279,11 @@ module.exports = class zb extends Exchange { const account = this.account (); const currencyId = this.safeString (balance, 'key'); const code = this.safeCurrencyCode (currencyId); - account['free'] = this.safeFloat (balance, 'available'); - account['used'] = this.safeFloat (balance, 'freez'); + account['free'] = this.safeString (balance, 'available'); + account['used'] = this.safeString (balance, 'freez'); result[code] = account; } - return this.parseBalance (result); + return this.parseBalance (result, false); } parseDepositAddress (depositAddress, currency = undefined) { @@ -321,18 +332,6 @@ module.exports = class zb extends Exchange { }; } - parseDepositAddresses (addresses, codes = undefined) { - let result = []; - for (let i = 0; i < addresses.length; i++) { - const address = this.parseDepositAddress (addresses[i]); - result.push (address); - } - if (codes) { - result = this.filterByArray (result, 'currency', codes); - } - return this.indexBy (result, 'currency'); - } - async fetchDepositAddresses (codes = undefined, params = {}) { await this.loadMarkets (); const response = await this.privateGetGetPayinAddress (params); @@ -439,16 +438,16 @@ module.exports = class zb extends Exchange { if (market !== undefined) { symbol = market['symbol']; } - const last = this.safeFloat (ticker, 'last'); + const last = this.safeNumber (ticker, 'last'); return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), - 'high': this.safeFloat (ticker, 'high'), - 'low': this.safeFloat (ticker, 'low'), - 'bid': this.safeFloat (ticker, 'buy'), + 'high': this.safeNumber (ticker, 'high'), + 'low': this.safeNumber (ticker, 'low'), + 'bid': this.safeNumber (ticker, 'buy'), 'bidVolume': undefined, - 'ask': this.safeFloat (ticker, 'sell'), + 'ask': this.safeNumber (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, @@ -458,12 +457,23 @@ module.exports = class zb extends Exchange { 'change': undefined, 'percentage': undefined, 'average': undefined, - 'baseVolume': this.safeFloat (ticker, 'vol'), + 'baseVolume': this.safeNumber (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; } + parseOHLCV (ohlcv, market = undefined) { + return [ + this.safeInteger (ohlcv, 0), + this.safeNumber (ohlcv, 1), + this.safeNumber (ohlcv, 2), + this.safeNumber (ohlcv, 3), + this.safeNumber (ohlcv, 4), + this.safeNumber (ohlcv, 5), + ]; + } + async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); const market = this.market (symbol); @@ -488,14 +498,12 @@ module.exports = class zb extends Exchange { let side = this.safeString (trade, 'trade_type'); side = (side === 'bid') ? 'buy' : 'sell'; const id = this.safeString (trade, 'tid'); - const price = this.safeFloat (trade, 'price'); - const amount = this.safeFloat (trade, 'amount'); - let cost = undefined; - if (price !== undefined) { - if (amount !== undefined) { - cost = price * amount; - } - } + const priceString = this.safeString (trade, 'price'); + const amountString = this.safeString (trade, 'amount'); + const costString = Precise.stringMul (priceString, amountString); + const price = this.parseNumber (priceString); + const amount = this.parseNumber (amountString); + const cost = this.parseNumber (costString); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; @@ -674,23 +682,13 @@ module.exports = class zb extends Exchange { const timestamp = this.safeInteger (order, 'trade_date'); const marketId = this.safeString (order, 'currency'); const symbol = this.safeSymbol (marketId, market, '_'); - const price = this.safeFloat (order, 'price'); - const filled = this.safeFloat (order, 'trade_amount'); - const amount = this.safeFloat (order, 'total_amount'); - let remaining = undefined; - if (amount !== undefined) { - if (filled !== undefined) { - remaining = amount - filled; - } - } - const cost = this.safeFloat (order, 'trade_money'); - let average = undefined; + const price = this.safeNumber (order, 'price'); + const filled = this.safeNumber (order, 'trade_amount'); + const amount = this.safeNumber (order, 'total_amount'); + const cost = this.safeNumber (order, 'trade_money'); const status = this.parseOrderStatus (this.safeString (order, 'status')); - if ((cost !== undefined) && (filled !== undefined) && (filled > 0)) { - average = cost / filled; - } const id = this.safeString (order, 'id'); - const feeCost = this.safeFloat (order, 'fees'); + const feeCost = this.safeNumber (order, 'fees'); let fee = undefined; if (feeCost !== undefined) { let feeCurrency = undefined; @@ -705,7 +703,7 @@ module.exports = class zb extends Exchange { 'currency': feeCurrency, }; } - return { + return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, @@ -719,15 +717,15 @@ module.exports = class zb extends Exchange { 'side': side, 'price': price, 'stopPrice': undefined, - 'average': average, + 'average': undefined, 'cost': cost, 'amount': amount, 'filled': filled, - 'remaining': remaining, + 'remaining': undefined, 'status': status, 'fee': fee, 'trades': undefined, - }; + }); } parseOrderStatus (status) { @@ -790,7 +788,7 @@ module.exports = class zb extends Exchange { // const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'hash'); - const amount = this.safeFloat (transaction, 'amount'); + const amount = this.safeNumber (transaction, 'amount'); let timestamp = this.parse8601 (this.safeString (transaction, 'submit_time')); timestamp = this.safeInteger (transaction, 'submitTime', timestamp); let address = this.safeString2 (transaction, 'toAddress', 'address'); @@ -810,7 +808,7 @@ module.exports = class zb extends Exchange { } const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); let fee = undefined; - const feeCost = this.safeFloat (transaction, 'fees'); + const feeCost = this.safeNumber (transaction, 'fees'); if (feeCost !== undefined) { fee = { 'cost': feeCost, @@ -843,7 +841,7 @@ module.exports = class zb extends Exchange { if (password === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires exchange.password or a safePwd parameter'); } - const fees = this.safeFloat (params, 'fees'); + const fees = this.safeNumber (params, 'fees'); if (fees === undefined) { throw new ArgumentsRequired (this.id + ' withdraw() requires a fees parameter'); } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/package.json b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/package.json index 1521ec10e..fa1f929a7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/package.json +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/node_modules/ccxt/package.json @@ -1,27 +1,27 @@ { - "_from": "ccxt@1.42.77", - "_id": "ccxt@1.42.77", + "_from": "ccxt@1.47.49", + "_id": "ccxt@1.47.49", "_inBundle": false, - "_integrity": "sha512-vPaw8G3hr9iq1iJ59EHuA6iqjufgK6dNC7MjT3qV8YQbpEJoD2ynoFwfl1hbuvlyKlFjiOa3gHwhRV64UacBDQ==", + "_integrity": "sha512-aGjOGKX/wfStwD24dH7FweP2ktdbZBjhgLxkipFVaewnjsftyiuzCCikMS7IvSRON/aAMG0oqKUdVHL382BFMA==", "_location": "/ccxt", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "ccxt@1.42.77", + "raw": "ccxt@1.47.49", "name": "ccxt", "escapedName": "ccxt", - "rawSpec": "1.42.77", + "rawSpec": "1.47.49", "saveSpec": null, - "fetchSpec": "1.42.77" + "fetchSpec": "1.47.49" }, "_requiredBy": [ "#USER", "/" ], - "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.42.77.tgz", - "_shasum": "8ab5f8e7190854e163da6d4fcf44530794d0a21c", - "_spec": "ccxt@1.42.77", + "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.47.49.tgz", + "_shasum": "ef9c41b5573b85d3b83cf1292d0aa891c4d5b6bc", + "_spec": "ccxt@1.47.49", "_where": "C:\\Superalgos\\Projects\\Superalgos\\TS\\Bot-Modules\\Trading-Bot\\Low-Frequency-Trading\\APIs", "author": { "name": "Igor Kroitor", @@ -543,7 +543,9 @@ "equos.io", "EQUOS", "ndax.io", - "NDAX" + "NDAX", + "ascendex.com", + "AscendEX" ], "license": "MIT", "main": "./ccxt.js", @@ -587,5 +589,5 @@ }, "types": "./ccxt.d.ts", "unpkg": "dist/ccxt.browser.js", - "version": "1.42.77" + "version": "1.47.49" } diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/package-lock.json b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/package-lock.json index 976144cc2..cd3bb8d9e 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/package-lock.json +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/APIs/package-lock.json @@ -3,9 +3,9 @@ "lockfileVersion": 1, "dependencies": { "ccxt": { - "version": "1.42.77", - "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.42.77.tgz", - "integrity": "sha512-vPaw8G3hr9iq1iJ59EHuA6iqjufgK6dNC7MjT3qV8YQbpEJoD2ynoFwfl1hbuvlyKlFjiOa3gHwhRV64UacBDQ==" + "version": "1.47.49", + "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.47.49.tgz", + "integrity": "sha512-aGjOGKX/wfStwD24dH7FweP2ktdbZBjhgLxkipFVaewnjsftyiuzCCikMS7IvSRON/aAMG0oqKUdVHL382BFMA==" } } } From 623227601276da44296b5be848bf42f53d6cb81e Mon Sep 17 00:00:00 2001 From: 9808us <9808us@pm.me> Date: Tue, 13 Apr 2021 09:58:57 +0200 Subject: [PATCH 31/32] This is my contribution to Superalgos --- ...bleshooting-016-browser-compatibility.json | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Projects/Superalgos/Schemas/Docs-Topics/troubleshooting-016-browser-compatibility.json diff --git a/Projects/Superalgos/Schemas/Docs-Topics/troubleshooting-016-browser-compatibility.json b/Projects/Superalgos/Schemas/Docs-Topics/troubleshooting-016-browser-compatibility.json new file mode 100644 index 000000000..5f4743244 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/troubleshooting-016-browser-compatibility.json @@ -0,0 +1,41 @@ +{ + "topic": "Troubleshooting", + "pageNumber": "16", + "type": "Browser Compatibility", + "definition": { + "text": "There is no recommended browser to use!", + "updated": 1618298878638 + }, + "paragraphs": [ + { + "style": "Text", + "text": "While there is no recommended browser to use with Superalgos, there is the need to use a common base for developers and users to develop SA and troubleshoot possible errors. As of today Chrome is one of the most used browser worldwide and that's why it's suggested to use it. Some users reported that Edge and Brave browser both based on chromium project are working with no (or minor) issues.", + "updated": 1618299516232 + }, + { + "style": "List", + "text": "Chrome -> Common base browser used by devs to develop SA and troubleshoot issues" + }, + { + "style": "List", + "text": "Edge -> Based on chromium, unknown issues" + }, + { + "style": "List", + "text": "Brave -> Based on chromium, unknown issues. Shields should be set down", + "updated": 1618300294258 + }, + { + "style": "List", + "text": "Firefox -> No reports, unknown" + }, + { + "style": "Text", + "text": "" + }, + { + "style": "Text", + "text": "" + } + ] +} \ No newline at end of file From b5c937bda5c90fda43219b2e0d18d620f2d5e688 Mon Sep 17 00:00:00 2001 From: Julian Molina Date: Tue, 13 Apr 2021 14:49:26 +0200 Subject: [PATCH 32/32] Contribute tutorial plugins-docs branch update --- .../how-to/create-plugins-docs-branch-01.png | Bin 200149 -> 0 bytes .../how-to/create-plugins-docs-branch-02.png | Bin 207718 -> 0 bytes .../how-to/create-plugins-docs-branch-03.png | Bin 189274 -> 0 bytes ...-the-plugins-docs-branch-in-old-forks.json | 85 +++++++++--------- 4 files changed, 43 insertions(+), 42 deletions(-) delete mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png delete mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-02.png delete mode 100644 Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-03.png diff --git a/Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png b/Projects/Superalgos/PNGs/Docs/how-to/create-plugins-docs-branch-01.png deleted file mode 100644 index 896944d887b434480179ad47ae695e7d88dc5dbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200149 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

hh_*N&%wk5 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ìX+7@eAx@Nu3LCwtE$Przj(UCICZHWR3 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


umSrmst4v*ht$EI_qJJvE()?jk` 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

hh_*N&%wk5 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�wI!$ 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 P)plugins-docs in the Field", - "updated": 1618156956365 + "style": "Subtitle", + "text": "1. Make sure you are on the Master branch", + "updated": 1618317374702 }, { "style": "Important", - "text": "Make sure the spelling is exact!" + "text": "You will create a branch using a Git command, but you must make sure that you create the new branch as a copy of the master branch. If you are currently running the software from a branch different than the master branch, you must first switch to the master branch, and only then create the new branch.", + "updated": 1618316571133 }, { - "style": "Json", - "text": "plugins-docs" - }, - { - "style": "Title", - "text": "4. Click the Create branch: plugins-docs from 'master' Button", - "updated": 1618156987815 - }, - { - "style": "Png", - "text": "PNGs/Superalgos/Docs/how-to/create-plugins-docs-branch-02.png", - "updated": 1618157499323 + "style": "Subtitle", + "text": "2. Create the plugins-docs branch", + "updated": 1618317383194 }, { "style": "Text", - "text": "You should end up with the confirmation that the new branch has been created.", - "updated": 1618157121114 + "text": "Start a new console/terminal window and change directories to the root of the Superalgos folder. Once there, run the following command:", + "updated": 1618316776970 }, { - "style": "Png", - "text": "PNGs/Superalgos/Docs/how-to/create-plugins-docs-branch-03.png", - "updated": 1618157524877 + "style": "Json", + "text": "git branch plugins-docs", + "updated": 1618316691052 }, { - "style": "Title", - "text": "5. That's it!" + "style": "Text", + "text": "You will likely NOT get any confirmation that the branch was created. Instead, you will get the prompt again. Run the following command to make sure the branch exists:", + "updated": 1618316910204 + }, + { + "style": "Json", + "text": "git branch --list", + "updated": 1618316915062 + }, + { + "style": "Text", + "text": "You should get a list of the existing local branches, one of which should be the plugins-docs branch.", + "updated": 1618316950598 }, { "style": "Success", - "text": "Now you may go back to the tutorial!" + "text": "That's it! Now you may go back to the tutorial!", + "updated": 1618317782493 } ] } \ No newline at end of file